0

我有一个 Literal 类,它实际上只是 (const int) 的包装器。我想要第二个类 PositiveLiteral,它继承自 Literal,但有一个构造函数断言其值为正数。

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 没有。这只是一种无需明确声明即可维护断言的方法。

在应该是一个简单的包装类中,不需要虚拟方法来完成相同任务的另一种方法是什么?

4

1 回答 1

1

delete除非您进行动态分配并通过指向基类的指针,否则您不需要拥有虚拟析构函数。


真正的问题在于设计层面。因为虽然每个PositiveLiteral值都是一个Literal值,但如果你有一个对 a 的引用,Literal它实际上是 a PositiveLiteral,那么你可以给它分配一个负值……

在文献和论坛讨论中,这曾经被称为椭圆与圆问题,尽管相似性并不明显。

首先,要非常清楚这个问题,仅对于不可变值aPositiveLiteral是 a Literal。mutable不是mutable的情况PositiveLiteralLiteral

然后,一个实用的 C++ 解决方案是提供值转换而不是使用继承。

例如,这是用于智能指针的解决方案。


附录:我没有看到在 OP 的代码中值为const. 所以不存在这样的问题。

一个实际的问题是,至少有一个编译器 Visual C++ 倾向于愚蠢地警告它无法生成复制赋值运算符。可以通过声明私有而不执行来关闭它。:-)

于 2013-12-11T06:03:46.730 回答