接口/抽象类是否只包含纯虚方法?

时间:2013-02-09 09:27:17

标签: c++

我在设计方面有点弱,我想知道在界面中使用简单的虚拟方法(不仅仅是纯虚拟)是否是一个好的设计?我有一个类是某种接口:

class IModel {
    void initialize(...);
    void render(...);

    int getVertexCount() const;
    int getAnotherField() const;
};

初始化和渲染方法需要重新实现,因此它们是纯虚方法的理想选择。但是,最后两种方法非常简单,实际上总是具有相同的实现(只返回一些字段)。我可以将它们作为具有默认实现的虚拟方法保留,还是将其作为需要重新实现的纯虚拟更好,因为它是一个接口?

3 个答案:

答案 0 :(得分:2)

我们必须指出一些不同之处:

没有“某种接口”这样的东西,这个类应该是接口还是抽象类?

如果它应该是一个接口,那么答案是:它的所有方法必须是纯虚拟(没有实现),它必须包含字段,甚至一个。你可以(必须,实际上)做的最多就像jaunchopanza所说的那样,为虚拟析构函数提供一个空体,从而允许派生类相应地被破坏。

相反,如果它应该是一个抽象类,那么你可以自由地添加字段m_vertexCountm_anotherField(我想)并实现getVertexCount()和getAnotherField() ,随你请。但是,您应将其命名为IModel,因为I前缀仅应用于接口。

编辑:我认为我是Bo Persson所谈论的那些“信徒”之一:)

答案 1 :(得分:1)

您正面临代码重复和可读性之间的权衡。您的代码的读者将从每个纯接口和每个非重写方法中获得很好的帮助。但是,默认实现将被每个子类复制。是否应该提供默认实现取决于默认实现将发生变化的可能性,然后需要在整个地方进行更改。

在不知道这些细节的情况下,无法给出一个难以肯定的答案。

答案 2 :(得分:0)

您可以做的一件事是使IModel成为接口并提供实现通用/重复功能的基类,例如ModelBase

class IModel
{
    virtual void initialize(...) = 0;
    virtual void render(...) = 0

    virtual int getVertexCount() const = 0;
    virtual int getAnotherField() const = 0;
};

class ModelBase : public IModel
{
    // common functions
    virtual int getVertexCount() const override { return vertexCount_; }
    virtual int getAnotherField() const override { return anotherField_; }

protected:
    int vertexCount_ = 0, anotherField_ = 0;
};

class MyModel : public ModelBase
{
    virtual void initialize(...) override { ... }
    virtual void render(...) override { ... }
};

这种方法的一个缺点是,由于额外的虚函数和编译器的优化损失,会导致一些性能损失(可能微不足道)。