Virtual static variable
我需要为类基的每个子代分配唯一的整数值,该子代应该可以通过使用指向这些类或其类型名的指针来访问。
我是这样实施的
1 2 3 4 5 | class Base { public: int idCompType = InvalidCompType; virtual int getCompType() = 0; } |
然后,在基的每个子代中,我应该声明idcomptype(用于模板)并重写getcomptype(用于指针):
1 2 3 4 5 | class Real1: public Base { public: int idCompType = 1; int getCompType() override { return idCompType; } } |
现在我可以找到从指针到基的comp类型
1 2 | Base *comp = getComp(...); std::cout << comp->getCompType(); |
或者在模板中使用类型名:
1 2 3 4 | template <typename T> int getType() { return T::idCompType; } |
在每个子类中,如果没有双重声明idcomptype和getcomptype(),是否有一种方法可以使其更简单?在对象Pascal中,我使用虚拟静态方法实现了这一点,但是它们在C++中是不允许的。
PS:问题不在于虚拟静态方法——虚拟静态方法只是可能的解决方案之一,我的问题是用其他语言解决的。
我的建议:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Base { public: virtual int getCompType() = 0; protected: static int getNextCompType() { static int nextType = 0; return ++nextType; } }; |
对派生类的更改:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Real1: public Base { public: static int getCompTypeImpl() { static int myType = Base::getNextCompType(); return myType; } int getCompType() override { return getCompTypeImpl(); } }; |
下面是一个工作程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #include <iostream> class Base { public: virtual int getCompType() = 0; protected: static int getNextCompType() { static int nextType = 0; return ++nextType; } }; class Real1: public Base { public: static int getCompTypeImpl() { static int myType = Base::getNextCompType(); return myType; } int getCompType() override { return getCompTypeImpl(); } }; class Real2: public Base { public: static int getCompTypeImpl() { static int myType = Base::getNextCompType(); return myType; } int getCompType() override { return getCompTypeImpl(); } }; template <typename T> int getCompType() { return T::getCompTypeImpl(); } int main() { Real1 v1; Real2 v2; std::cout << v1.getCompType() << std::endl; std::cout << v2.getCompType() << std::endl; std::cout << getCompType<Real1>() << std::endl; std::cout << getCompType<Real2>() << std::endl; }; |
输出:
1 2 3 4 | 1 2 1 2 |
@r sahu答案的另一个变化是消除派生类中代码的重复:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #include <iostream> class Base { public: virtual int getCompType() const = 0; template <typename T> static int getCompTypeOf() { static int compType = getNextCompType(); return compType; } private: static int getNextCompType() { static int nextType = 0; return ++nextType; } }; template <typename Derived, typename DeriveFrom = Base> class TypeAssigner : DeriveFrom { public: int getCompType() const override { return Base::getCompTypeOf<Derived>(); } }; class Real1: public TypeAssigner<Real1> {}; class Real2: public TypeAssigner<Real2> {}; class Real3 : public TypeAssigner<Real3, Real2> {}; int main() { Real1 v1; Real2 v2; Real3 v3; std::cout << v1.getCompType() << ' '; std::cout << v2.getCompType() << ' '; std::cout << v3.getCompType() << ' '; std::cout << Base::getCompTypeOf<Real1>() << ' '; std::cout << Base::getCompTypeOf<Real2>() << ' '; std::cout << Base::getCompTypeOf<Real3>() << ' '; }; |
这里是@sahu版本的一个微小变体。不要在每个派生类中实现相同的
1 2 3 4 5 | template<typename T> static int getCompTypeImpl() { return getNextCompType<T>(); } |
修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | template<typename T> static int getNextCompType() { auto iter = m_table.find(std::type_index(typeid(T))); if (iter != m_table.end()) { return iter->second; } else { m_table.insert(std::make_pair(std::type_index(typeid(T)), ++nextType)); return nextType; } } |
最后介绍了两个新的静态数据成员。
1 2 3 | private: static std::map<std::type_index, int> m_table; static int nextType; |
请在这里找到完整的代码。
诚然,这引入了两个新的静态成员,并做了更多的工作比原始版本的萨胡。但是,这消除了在所有派生类。