避免代码重复

Avoiding duplication of code

本文关键字:代码      更新时间:2023-10-16

请参考以下示例。

using namespace std;
//Base interface
class IBase
{
public:
    virtual void BaseMethod1() = 0;
    virtual void BaseMethod2() = 0;
};
class IEntity1 : public IBase
{
public:
    virtual void Entity1Method1() = 0;
    virtual void Entity1Method2() = 0;
};
class Entity1 : public IEntity1
{
public:
    Entity();
//IBaseMethods
    void BaseMethod1();
    void BaseMethod2();
//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//EntityMethods
    void Method1();
    void Method2();
};

在上面的例子中,对于从IBase派生的所有其他实体,需要实现BaseMethod1()和BaseMethod2()。由于哪些代码重复而发生?无论如何,我们可以避免在派生的实体中冗余实现IBase方法吗?

您可以将虚拟继承与默认基实现类结合使用来封装默认基行为,并使其仅由所需的具体类继承,如下所示:

using namespace std;
//Base interface
class IBase
{
public:
    virtual void BaseMethod1() = 0;
    virtual void BaseMethod2() = 0;
};
class IEntity1 : virtual public IBase
{
public:
    virtual void Entity1Method1() = 0;
    virtual void Entity1Method2() = 0;
};
class BaseImpl : virtual public IBase
{
public:
    virtual void BaseMethod1()
    {
        ...
    }
    virtual void BaseMethod2()
    {
        ...
    }
}
class Entity1 : public IEntity1, public BaseImpl
{
public:
    Entity1();
//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//EntityMethods
    void Method1();
    void Method2();
};

但是,存在与虚拟继承相关的运行时成本。多重继承也带来了一些结构问题,例如基类构造。

您甚至可以使用模板类获得一些乐趣,以使您的类组合更加模块化:

template<typename TEntity, typename TBaseImpl>
class ConcreteEntity: public TEntity, public TBaseImpl
{
public:
    ConcreteEntity() {}
};
class ConreteEntity1 : public ConcreteEntity<IEntity1, BaseImpl>
{
public:
    ConreteEntity1();
//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//ConreteEntity1 Methods
    void Method1();
    void Method2();
};

您可以创建一个在 BaseMethod1() 实现中调用的相同函数。

像这样:

void BaseMethod1_common();
class Entity1 : public IEntity1
{
public:
    Entity();
//IBaseMethods
    void BaseMethod1() { BaseMethod1_common(); }
    void BaseMethod2();
//IEntityMethods
    void Entity1Method1();
    void Entity1Method2();
//EntityMethods
    void Method1();
    void Method2();
};

首先,IBase 应该有一个虚拟析构函数。

声明它是纯虚拟并定义 IBase:BaseMethod1() 和IBase::BaseMethod1().

如果你的目的是隐藏实现,那么唯一的选择是将代码作为库发布,然后只在其他开发人员之间共享头文件。

实现

全局函数或按照建议使用多重继承仍然意味着您的实现是公开的。

但是,如果目的是减少各种类之间的耦合,还有另一种选择:

  • 创建一个具有实际共享实现的类,然后创建另一个类,该类将成为它的接口。
  • 然后,此接口类将成为其他派生实体的基类。

示例代码如下所示:

//First Header and Cpp file
class Base_private
{
public:
    BaseImpl(arguments);
    ~BaseImpl();
    void BaseMethod1() {
        //Implementation
    }
    void BaseMethod2() {
        //Implementation
    }
};
//Second Header and Cpp file
class BaseInterface
{
public:
    BaseInterface(arguments);
    ~BaseInterface();
    void BaseMethod1() {
        m_pBase->BaseMethod1();
    }
    void BaseMethod2() {
        m_pBase->BaseMethod2();
    }
private:
    Base_private* m_pBase;
};
class Entity : public BaseInterface
{
public:
    Entity(arguments);
    ~Entity();
    void Method1();
    void Method2();
};