在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=Univ
,C2=College
等。我有一个std::map<Key, EduInst*>
存储所有在运行时生成的机构取决于用户输入。有时我只需要在Univ
或College
s上操作。实现这个的好方法是什么?
答案 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) {}
};