c ++如何在派生类中实现const静态成员

时间:2015-12-07 11:13:45

标签: c++ oop inheritance static const

在C ++中,我有几个继承自抽象超类的类。子类具有共享相同名称type的静态属性,但当然具有不同的值。我的问题是实现这个的最佳方法是什么,以及每个实现的优缺点是什么。

PS: 有一些相关的讨论,如here,但大多数都没有解释为什么不应该使用下面的方法(在我的机器上工作)1。此外,方法2中的子类方法不是静态的,并且必须获取一个实例来调用它们。

Apporach 1:超类中未初始化的const static

class Abstract {
  public:
    const static int type;
};

class C1: public Abstract {
  public:
    const static int type = 1;
};

class C2 : public Abstract {
  public:
    const static int type = 2;
};

方法2:使用虚函数代替变量

class Abstract {
  public:
    virtual int get_type() = 0;
};

class C1: public Abstract {
  public:
    int get_type() {return 1;}
};

class C2 : public Abstract {
  public:
    int get_type() {return 2;}
};

我不知道的其他方法......

修改

正如下面提到的一些答案/评论,我试图在运行时识别实际类型。但是我无法想到更好的设计。

为了使其具体化,我们假设Abstract=EduInst用于教育机构,C1=UnivC2=College等。我有一个std::map<Key, EduInst*>存储所有在运行时生成的机构取决于用户输入。有时我只需要在UnivCollege s上操作。实现这个的好方法是什么?

2 个答案:

答案 0 :(得分:2)

首先是警告:

继承描述了与基类的“某种”关系。只有当你在同一个容器中存储不同类型的对象时才会有意义,当这些类型的对象绝对共享同一个接口时,并且当任何一个派生类都不需要特殊处理时(即当你,对象的消费者)不要需要知道它的类型。)

此外,如果你只有几种相同的东西,并且这些东西在编译时可能是已知的,那么使用继承可能是错误的。

如果您的继承对象必须向客户端标识其实际类型,这进一步证明继承是错误的解决方案 - 因为现在您将使用代码来查找代码,这是一个坏主意(它不可测试,当你的程序处于你没预料到的状态时,它可能会出错。

此外,如果您的对象不同但需要存储在同一个容器中,那么boost::variant可能是您正在寻找的解决方案。然后,您将使用boost::static_visitor对变体中的对象执行操作。这样做的好处是绝对类型安全,编译器不允许您忘记处理类型。

说完了所有......

方法1不起作用,因为如果你已经拥有派生类的类型,你将始终获得基类的类型。

方法2可行,但它很可怕并且表明设计已经破碎。

答案 1 :(得分:1)

你不能拥有&#34;虚拟&#34;静态成员。

方法一是找出&#34;类型&#34;一个类的属性,第二个用于查找&#34;类型&#34;实例的属性 换句话说:要使用第一个,你需要知道课程;要使用第二个,你需要知道实例 在你不知道的情况下编写代码是不可能的。

请注意,如果在基类中的函数内使用type,则方法1可能会给您带来意外结果 例如,

class Abstract
{
public:
    int get_type() const { return type; }
};

// ...
C1 c;
std::cout << c.get_type(); 

将输出0,因为这是Abstract::type的值。

如果牺牲另一个成员的空间,第二种方法的变体可以避免虚函数:

class Abstract {
  public:
    // ...
    int get_type() const { return type; }
  protected:
    Abstract(int t) : type(t) {}
  private:
    int type;
};

class C1: public Abstract {
  public:
    C1() : Abstract(1) {}
};

class C2 : public Abstract {
  public:
    C2() : Abstract(2) {}
};