2

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

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

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

初始化和渲染方法肯定需要重新实现,因此它们是纯虚拟方法的良好候选者。但是,最后两种方法非常简单,并且几乎总是具有相同的实现(只是返回一些字段)。我可以将它们保留为具有默认实现的虚拟方法,还是让它需要重新实现的纯虚拟更好,因为它是一个接口?

4

3 回答 3

2

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

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

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

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

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

于 2013-02-09T09:39:06.693 回答
1

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

在不了解这些细节的情况下,无法给出一个艰难的是或否的答案。

于 2013-02-09T09:41:15.023 回答
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 { ... }
};

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

于 2018-08-22T02:48:22.813 回答