虚拟静态变量

时间:2015-03-16 05:05:15

标签: c++ c++11

我需要为类 Base 的每个后代分配唯一的整数值,这些后代应该可以通过使用指向这些类或其类型名的指针来访问。

我这样实现了

class Base {
public:
  int idCompType = InvalidCompType;
  virtual int getCompType() = 0;
}

然后在base的每个后代我应声明idCompType(对于模板)并覆盖getCompType(用于指针):

class Real1: public Base {
public:
  int idCompType = 1;
  int getCompType() override { return idCompType; }
}

现在我可以从指针到基础

找到comp类型
Base *comp = getComp(...);
std::cout << comp->getCompType();

或在模板中使用typename:

template <typename T>
int getType() {
  return T::idCompType;
}

如果没有在每个后代类中使用双重声明idCompType和getCompType(),有没有办法让它变得更简单?在Object Pascal中,我使用虚拟静态方法实现了这一点,但在C ++中不允许使用它们。

PS:问题不在于虚拟静态方法 - 虚拟静态方法只是可能的解决方案之一,也是我用其他语言解决问题的方法。

3 个答案:

答案 0 :(得分:1)

我的建议:

Base的更改:

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();
  }
};

这是一个工作计划:

#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
1
2

答案 1 :(得分:0)

这是@ Sahu版本的略微变体。 不是在每个派生类中实现相同的getCompTypeImpl(),而是将其放在Base类中。

template<typename T>
static int getCompTypeImpl()
{
    return getNextCompType<T>();
}   

getNextCompType()修改为

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;
    }
}   

最后介绍2个新的静态数据成员。

private:
    static std::map<std::type_index, int> m_table;
    static int nextType;

请查看完整代码here

不可否认,这引入了2个新的静态成员,并且做了更多的工作 比Sahu的原始版本。但是,这消除了实施方法的负担 所有派生类。

答案 2 :(得分:0)

@R Sahu的另一个变体是消除派生类中代码重复的答案:

#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() << '\n';
   std::cout << v2.getCompType() << '\n';
   std::cout << v3.getCompType() << '\n';

   std::cout << Base::getCompTypeOf<Real1>() << '\n';
   std::cout << Base::getCompTypeOf<Real2>() << '\n';
   std::cout << Base::getCompTypeOf<Real3>() << '\n';
};