接口/抽象类应该只包含纯虚拟方法

Should interface/abstract class contains only pure virtual methods?

本文关键字:包含纯 虚拟 方法 抽象类 接口      更新时间:2023-10-16

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

class IModel {
    void initialize(...);
    void render(...);
    int getVertexCount() const;
    int getAnotherField() const;
};

initialize和render方法肯定需要重新实现,因此它们是纯虚拟方法的好候选者。然而,最后两种方法非常简单,而且实际上总是具有相同的实现(只是返回一些字段)。我可以把它们作为默认实现的虚拟方法吗?还是因为它是一个接口,所以最好让它成为需要重新实现的纯虚拟方法?

我们必须指出一些差异:

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

如果它应该是一个接口,那么答案是:它的所有方法都必须是纯虚拟(无实现),并且它必须不包含字段,甚至一个字段都不包含。正如jaunchopanza所说,你能(实际上必须)做的最多的事情就是给虚拟析构函数一个空体,从而允许相应地析构函数派生类。

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

编辑:我想我是Bo Persson所说的"信徒"之一:)

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

如果不了解这些细节,就无法给出一个明确的"是"或"否"的答案。

您可以做的一件事是使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 { ... }
};

这种方法的一个缺点是,由于额外的虚拟函数和编译器的优化损失,会有一些(可能可以忽略不计)性能损失。