【问题标题】:c++: Multiple inheritance and interfacec++:多重继承和接口
【发布时间】:2022-08-12 00:58:36
【问题描述】:

请参见以下代码:

#include <iostream>

struct A {  // Interface
    virtual void a() = 0;
    virtual void x() = 0;
};

struct B {
    virtual void a() { std::cout << \"B\" << std::endl; }
};

struct C : A, B {
    void a() override { B::a(); }
    void x() override { std::cout << \"x\" << std::endl; }
};

int main() {
    C c;
    c.a();
    c.x();
}

此代码有效。问题是它是否是最佳/最佳解决方案。

我想知道是否有任何技巧可以让我不在 C 类中创建 a() 。

更新:我更正了代码以说明为什么 B 不能从 A 继承。

更新 2:

#include <iostream>
    
struct I1 {
    virtual void i1() = 0;
};

struct I2 {
    virtual void i2() = 0;
};

struct I3 : I1, I2 {};

struct A : I1 {
    void i1() override { std::cout << \"i1\" << std::endl; }
};

struct B : A, I2 {
    void i2() override { std::cout << \"i2\" << std::endl; }
};

int main() {
    B b;
    b.i1();
    b.i2();

    I3* ptr = dynamic_cast<I3*>(&b);  // warning: dynamic_cast of ‘B b’ to ‘struct I3*’ can never succeed
    std::cout << ptr << std::endl;
}

问题是:如何通过接口传递指向\'b\'的指针?为什么 b 不能转换为 I3 接口?

  • 是的。使 \'B\' 从 \'A\' 继承并完全跳过多重继承。
  • 你说的最好是什么意思?请注意,有两个虚拟方法,都被C::a 覆盖,这是你想要的吗?
  • 什么的最佳/可选解决方案?您发布的代码只是做了它所做的事情,但您没有说出您真正想要实现的目标。
  • 您可以将A 拆分为 2 个接口 - 一个可以由B 派生和实现。那么C可以继承B(用于实现a)和新的拆分接口(用于实现x)。
  • 你错过了virtual destructor

标签: c++ multiple-inheritance


【解决方案1】:

可以考虑将A拆分成2个接口:

struct A1 {  // Interface1
    virtual void a() = 0;
    virtual ~A1() {}
};

struct A2 {  // Interface2
    virtual void x() = 0;
    virtual ~A2() {}
};

这样您就可以:

  1. 使B 继承自A1 并实现a()
  2. 使C 继承自A2(以实现x())和B 以获取a() 的实现。

    见下文:

    #include <iostream>
    
    struct B : public A1 {
        virtual void a() override { std::cout << "B" << std::endl; }
    };
    
    struct C : public A2, public B {
        virtual void x() override { std::cout << "x" << std::endl; }
    };
    
    int main() {
        C c;
        c.a();
        c.x();
    }
    

    笔记:我在基类中添加了虚拟析构函数。在这里查看原因:When to use virtual destructors?

【讨论】:

  • 我省略了虚拟析构函数以使代码更简单。假设我需要将实现两个接口的对象传递给函数。然后我需要一个额外的接口来合并这两者,对吗?
  • 您的问题中没有提到这一点,但答案是肯定的。问题是你需要让C 继承这个“合并接口”和B,你会得到继承菱形问题。您可以在我的问题中看到我尝试处理它:stackoverflow.com/questions/71818055/…
  • 您可以考虑修改您的函数以接受 2 个接口,然后为这两个接口传递您的 C 实例。如果不熟悉系统的所有要求,就很难确定最佳设计。
【解决方案2】:

根据您要实现的目标,您可以使用类并将 B 中的函数设为私有,因此没有人可以尝试使用它。就像是:

class A {  // Interface
public:
    virtual ~A() {}

    virtual void a() = 0;
    virtual void x() = 0;
};

class B : public A{
private:
    void x() { std::exception("Not Implemented"); };

public:
    ~B() override{}
    void a() override { std::cout << "B" << std::endl; }
};

class C : public B {
public:
    ~C() override{}
    void x() override { std::cout << "x" << std::endl; }
};

其他可能的解决方案是:

  • 将 B 作为 C 的成员,因此您可以调用 B.a() 而不是多重继承,以减少对读者的混淆
struct A {  // Interface
    virtual ~A() {}
    virtual void a() = 0;
    virtual void x() = 0;
};

struct B {
    virtual void a() { std::cout << "B" << std::endl; }
};

struct C : A {
    B b;

    virtual ~C() override {}
    void a() override { b.a(); }
    void x() override { std::cout << "x" << std::endl; }
};

int main() {
    C c;
    c.a();
    c.x();
}

您可以使用函数指针 - 但这意味着函数必须是静态的,并且您的基类成为抽象类

struct A {  // Interface
    virtual ~A() {}

    
    virtual void x() = 0;
    typedef void(*aFunction)();
    aFunction a;

    A() { a = nullptr; }
   
};

struct B {
    static void a() { std::cout << "B" << std::endl; }
};

struct C : A {
    virtual ~C() {}

    void x() override { std::cout << "x" << std::endl; }
    C() { a = B::a; }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-30
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 2011-07-31
    • 2013-03-31
    • 2012-05-13
    相关资源
    最近更新 更多