抽象类在多继承中的应用

工程上的多继承

  • 被实际开发经验抛弃的多继承;
  • 工程开发中真正意义上的多继承是几乎不被使用的;
  • 多继承带来的代码复杂性远多于其带来的便利;
  • 多继承对代码维护上的影响是灾难性的;
  • 在设计方法上,任何多继承都可以用但继承代替

多继承的二义性和无法解决的问题

  • 多继承的二义性:用声明虚基类解决
#include <iostream>
//将B声明为虚基类,由C类的对象访问B类成员不会产生二义性
class B
{
public:
    int b;
    B():b(0){std::cout << "调用了构造函数B()" << std::endl;}
};

class B1 : virtual public B//声明为虚基类
{
public:
    int b1;
    B1():b1(0){std::cout << "调用了构造函数B1()" << std::endl;}
};

class B2 : virtual public B//声明为虚基类
{
public:
    int b2;
    B2():b2(0){std::cout << "调用了构造函数B2()" << std::endl;}
};

class C : public B1, public B2
{
public:
    int c;
    C():c(0){std::cout << "调用了构造函数C()" << std::endl;}
};

int main()
{
    C my_c;
    my_c.b = 10;
    std::cout << "B::b = " << my_c.b << std::endl;

    return 0;
}

执行结果:
这里写图片描述
可以看出,定义一个C类对象,会调用一次B类的构造函数B()。若去掉 virtual 关键字,即程序为:

#include <iostream>

class B
{
public:
    int b;
    B():b(0){std::cout << "调用了构造函数B()" << std::endl;}
};

class B1 : public B//声明为虚基类
{
public:
    int b1;
    B1():b1(0){std::cout << "调用了构造函数B1()" << std::endl;}
};

class B2 : public B//声明为虚基类
{
public:
    int b2;
    B2():b2(0){std::cout << "调用了构造函数B2()" << std::endl;}
};

class C : public B1, public B2
{
public:
    int c;
    C():c(0){std::cout << "调用了构造函数C()" << std::endl;}
};

int main()
{
    C my_c;

    return 0;
}

执行结果为:
这里写图片描述
调用了两次B类的构造函数,且访问B类的数据成员b时,会产生二义性。

  • 多继承中无法解决的问题
    看如下程序:
#include <iostream>

class B1
{
public:
    int b;
    B1():b(0){std::cout << "调用了构造函数B1()" << std::endl;}
};

class B2
{
public:
    int b;
    B2():b(0){std::cout << "调用了构造函数B2()" << std::endl;}
};

class C : public B1, public B2
{
public:
    int c;
    C():c(0){std::cout << "调用了构造函数C()" << std::endl;}
};

int main()
{
    C my_c;
    my_c.b = 10;

    return 0;
}

产生错误:
这里写图片描述
产生二义性。

抽象类在多继承中的应用

  • 一个派生类继承于两个抽象基类,即使这两个抽象基类有相同的成员函数,只要将其声明为纯虚函数,就不会产生二义性。程序如下:
#include <iostream>

class Interface1
{
public:
    virtual void add(int, int) = 0;
    virtual void print() = 0;
};

class Interface2
{
public:
    virtual void mult(int, int) = 0;
    virtual void print() = 0;
};

class Parent
{
public:
    void display()
    {
        std::cout << "Parent::display()执行" << std::endl;
    }
};

class Child : public Parent, public Interface1, public Interface2
{
public:
    virtual void add(int a, int b)
    {
        std::cout << "Child::add(int, int)执行" << std::endl;
        std::cout << "a = " << a << "; "
                  << "b = " << b << "; "
                  << "a + b = " << a + b << std::endl;
    }
    virtual void mult(int a, int b)
    {
        std::cout << "Child::mult(int, int)执行" << std::endl;
        std::cout << "a = " << a << "; "
                  << "b = " << b << "; "
                  << "a * b = " << a * b << std::endl;
    }
    virtual void print()
    {
        std::cout << "Child::print()执行" << std::endl;
    }
};

int main()
{
    Child ch;
    ch.print();
    ch.display();

    Interface1 * inter1 = &ch;
    Interface2 * inter2 = &ch;
    inter1->add(1, 2);
    inter1->print();
    inter2->mult(2, 3);
    inter2->print();

    return 0;
}

执行结果:
这里写图片描述
即使两个抽象基类 Interface1 和 Interface2 都有 print() 成员函数(纯虚函数),也没有产生二义性。

猜你喜欢

转载自blog.csdn.net/qq_40579095/article/details/81877308