c++:对于多重继承类的子类中的重复成员字段,什么是好的重构

c++: What is a good refactor for a duplicate member field in the subclass of a multiply-inherited class?

本文关键字:字段 成员 什么 重构 多重继承 c++ 子类      更新时间:2023-10-16

欢迎对问题进行更好的编辑。

我想以某种方式重构这三个类以删除class C中表示的重复字段(请参阅层次结构)。我想过将字段拉到父类中,但问题是 A 和 B 不够相似,不能被视为"is-a",C 被视为两者,而且它实际上只是一个成员字段,因此创建一个类只是为了保存一件事似乎有点矫枉过正。

等级制度:

(abstract data type)
class A : public O {
    public:
    //...
    std::string GetName();
    std::string GetName() const;
    void SetName(std::string name);
    //...
    protected:
    //...
    std::string _name;
    //...
};
//Methods and fields shown here represent the exact same representative data as in A but the classes are so dissimilar as to not be considered "is-a" relationship.
(abstract data type)
class B {
    public:
    //...
    std::string GetName();
    std::string GetName() const;
    void SetName(std::string name);
    //...
    protected:
    //...
    std::string _name;
    //...
};
(concrete)
class C : public A, public B {
    public:
    //...
    C(/*..Other parameters..*/, std::string name, /*....*/)
    : A(name, /*...*/), B(name, /*...*/) {
        /*...*/
    }
    //...
    private:
    //...        
};

如前所述,您可以保持原样,也可以考虑对类 C 使用组合而不是继承,例如:

class C : public A
{
public:
    // ...
    // The GetName and SetName methods are inherited from A.
private:
    B* b;
};

class C
{
public:
    // ...
    std::string GetName();
    std::string GetName() const;
    void SetName(std::string name);
private:
    A* a;
    B* b;
};

看看这个问题和答案:摆脱丑陋的 if 语句清楚地表明,正如@Andre提到的,你当前的代码是完全可以接受的,试图"修复"它可能会导致同样的痛苦和头脑打击。

保持原样,这很好。

由于C将相同的name参数传递给AB,因此您可以通过虚拟继承获得所需的内容。 下面的V被定义为ABC的公共基类,但是通过虚拟继承,它们都共享同一个实例。

class V {
    public:
    std::string GetName();
    std::string GetName() const;
    void SetName(std::string name);
    protected:
    std::string _name;
    V () {}
    V (std::string n) : _name(n) {}
    ~V () {}
};
class A : virtual public V, public O {
    //...
};
class B : virtual public V {
    //...
};
class C : virtual public V, public A, public B {
    public:
    C (/*...otherargs,*/std::string name/*,moreargs...*/)
        : V(name), A(/*...*/), B(/*...*/) {
        //...
    }
    //...
};