我有一个类Literal,它实际上只是(const int)的包装器。我想要一个继承自Literal的第二个类PositiveLiteral,但是有一个构造函数断言它的值是正的。
class Literal {
public:
Literal(int x):x(x){}
virtual ~Literal(){}
// Other methods
private:
const int x;
}
class PositiveLiteral : public Literal {
public:
PositiveLiteral(int x):Literal(x) {
assert(x > 0)
}
}
通过这种方式,期望正文字的函数可以简单地将PositiveLiteral作为参数。然后我不需要在我的代码中放置显式断言,而且,如果这些断言失败,我可以立即看到原因。
除了在这种情况下,我不希望继承Literal。然而,因为有继承,我必须给Literal一个虚拟析构函数,以避免看似愚蠢的未定义行为,因为PositiveLiteral没有与Literal没有关联的exra信息。这只是一种维护断言而不必明确的方法。
完成相同任务的另一种方法是什么,而不需要在一个简单的包装类中使用虚方法?
答案 0 :(得分:1)
除非你通过指向基类的指针进行动态分配和delete
,否则你不需要拥有虚拟析构函数。
真正的问题在于设计层面。虽然每个PositiveLiteral
值都是Literal
值,但如果您引用的Literal
实际上是PositiveLiteral
,则可以为其分配负值...
在文献和论坛讨论中,这曾被称为椭圆与圆形问题,尽管相似性并不明显。
首先,要明确问题,只有不可变值,PositiveLiteral
是Literal
。 不可变PositiveLiteral
是可变Literal
的情况。
然后,实用的C ++解决方案是提供值转换而不是使用继承。
例如,这是用于智能指针的解决方案。
附录:我没有在OP的代码中看到该值为const
。所以没有这样的问题。
实际问题是至少有一个编译器Visual C ++倾向于愚蠢地警告它无法生成一个拷贝赋值运算符;它可以通过声明一个没有实现的私有来关闭。 : - )