我可以从静态基本方法获取当前类类型ID吗?

时间:2018-03-20 00:47:36

标签: c++ oop c++11

无论如何从静态基类方法中获取类型?例如

{{1}}

由于C ++缺少静态变量重载,我很难找到一种方法来确定跨类的类类型,而不是在每个子类中都有一个特殊的虚函数,我试图避免由于它的数量。 / p>

4 个答案:

答案 0 :(得分:2)

创建一个将成为模板的课程 它的子类。将子类型作为模板参数传递 有了这个,基类就会知道孩子。 T将是子类型。

代码:

#include <iostream>
using namespace std;

template<typename T> class thebase
{
  static T instance;
public:
  static T& getInstance() { return instance; }
};

template <typename T> T thebase<T>::instance;

class sub1 : public thebase<sub1> {
public: void tell() { std::cout << "hello1: " << this << std::endl; }
};

class sub2 : public thebase<sub2> {
public: void tell() { std::cout << "hello2: " << this << std::endl; }
};

int main() {
  sub1& ref1 = sub1::getInstance();
  sub1& ref2 = sub1::getInstance();
  std::cout << ((&ref1) == (&ref2)) << std::endl;
  sub1::getInstance().tell();
  sub2::getInstance().tell();
  sub1::getInstance().tell();
  sub2::getInstance().tell();
  return 0;
}

输出:

1
hello1: 0x55874bff1193
hello2: 0x55874bff1192
hello1: 0x55874bff1193
hello2: 0x55874bff1192

这种代码模式有时称为CRTP

答案 1 :(得分:2)

  

归结为有一个经理类可以跟踪各种类及其状态的一个实例。你可以使用这个单例&#34;实例&#34;这些子类,但我希望能够说MySubClass :: instance(),然后让它从管理器中获取正确的实例,而不必在每个子类中编写它。

您可以使用CRTP ("Curiously recurring template pattern")实现托管类,以便基类知道派生类类型,然后可以将该信息委托给管理器类。

尝试这样的事情:

#include <map>
#include <typeinfo>
#include <typeindex>

class Base {
public:
    virtual ~Base() {}
};

class Manager
{
private:
    static std::map<std::type_index, Base*> m_instances;

public:
    template<typename T>
    static void addInstance(Base *inst) {
        if (!m_instances.insert(std::make_pair(std::type_index(typeid(T)), inst)).second)
            throw ...; // only 1 instance allowed at a time!
    }

    template<typename T>
    static void removeInstance() {
        auto iter = m_instances.find(std::type_index(typeid(T)));
        if (iter != m_instances.end())
            m_instances.erase(iter);
    }

    template<typename T>
    static T* getInstance() {        
        auto iter = m_instances.find(std::type_index(typeid(T)));
        if (iter != m_instances.end())
            return static_cast<T*>(iter->second);
        return nullptr;
    }
};

std::map<std::type_index, Base*> Manager::m_instances;

template<class Derived>
class A : public Base
{
public:
    A() {
        Manager::addInstance<Derived>(this);
    }

    ~A() {
        Manager::removeInstance<Derived>();
    }

    static Derived* getInstance() {
        return Manager::getInstance<Derived>();
    }
};

class B : public A<B>
{
    ...
};

class C : public A<C>
{
    ...
};

B b_inst;
C c_inst;

...

B *pB = B::getInstance();
if (pB) ...

C *pC = C::getInstance();
if (pC) ...

Live Demo

答案 2 :(得分:1)

根据你自己答案中自己的代码示例,这是最终的结果:

# include <iostream>
# include <typeinfo>

template <class T> 
class A
{
public:
    static const std::type_info& getClassType()
    {
        return typeid(T);
    }
};

class B : public A<B>
{ /* ... */ };

class C : public A<C>
{ /* ... */};

class D : public A<D>
{ /* ... */};

int main()
{
    B b; C c; D d;
    auto& b_type = b.getClassType();
    auto& c_type = c.getClassType();
    auto& d_type = d.getClassType();

    std::cout << b_type.name() << std::endl;
    std::cout << c_type.name() << std::endl;
    std::cout << d_type.name() << std::endl;
}
  

输出:   1B 1C 1D

答案 3 :(得分:0)

上面提到过CRTP或“奇怪的重复模板模式”。使用这个,我还没有测试过,但似乎我可以写:

template <class T> 
class A
{
    static std::type_info getClassType
    {
        return typeid(T);
    }
};


class B : public A<B>
{

};

B instance;
auto my_type = instance::getClassType()