簡體   English   中英

c++:多重繼承和接口

[英]c++: Multiple inheritance and interface

請參見以下代碼:

#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 接口?

您可以考慮將A拆分為 2 個接口:

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

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

這樣您就可以:

  1. 使BA1繼承並實現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();
}

注意:我在基類中添加了虛擬析構函數。 看這里為什么: 什么時候使用虛擬析構函數? .

根據您要實現的目標,您可以使用類並將 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 的成員,因此您可以調用 Ba() 而不是多重繼承,以減少對讀者的混淆
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; }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM