zoukankan      html  css  js  c++  java
  • C++ 虚基类 派生与继承

    在学习设计模式时我就有一个疑问,关联和继承除了用法上的区别,好像在内存上并没有什么区别,继承也是父类作为了子类的元素(内存上),关联也是这样。而且关联好像更占内存一些。这就是设计模式里问题了“依赖倒转原则”。

    继承分为public继承,protect继承,private继承

    public:父类中的public,protected成员到了派生类中属性不变。

    protected:父类中的public,protected成员到了派生类中,都变为protected成员。

    private:父类中的public,protected成员到了派生类中,都变成了private成员。

    特别注意:父类中的private成员是不会被继承到子类中的(这也是关联和继承的一个区别)。

    特别注意:还有一种继承被称为虚继承

    详细回顾一下虚继承:

    虚继承的形式:

    class 派生类:virtual public 基类1,virtual public 基类2, virtual public 基类3……

    {
    };

    构造函数过程:

    首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;

    执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;

    执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;

    执行派生类自己的构造函数;

    析构以与构造相反的顺序执行;

    虚继承的实质是,在多继承中,派生类的基类中如果有过个基类继承至同一基类,那么这几个基类肯定含有这同一基类的拷贝(各自各一份),所以在派生类中如果想使用,就必须加上作用域分辨符来唯一识别。这时如果另这些基类继承时用上虚基类就可以解决这个问题了。我们可以将共同继承的基类,设为虚基类,这时从不同路径继承过来的同名的数据成员在内存中就只有一份拷贝, 同名函数也只有一个映射。

     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 class Base
     6 {
     7 private:
     8     int val;
     9 public:
    10     Base(){ cout << "Base无参构造函数" << endl; };
    11     Base(int val){ this->val = val; cout << "Base有参构造函数" << endl; }
    12     void print(){ cout << "val = "<<val << endl; }
    13 };
    14 
    15 class Sub1 :virtual public Base
    16 {
    17 public :
    18     Sub1(int val) :Base(val){ cout << "Sub1含参构造函数" << endl; };
    19 };
    20 
    21 class Sub2 :virtual public Base
    22 {
    23 public:
    24     Sub2(int val) :Base(val){ cout << "Sub2含参构造函数" << endl; }
    25 };
    26 
    27 class Child :public Sub1, public Sub2
    28 {
    29 public :
    30     Child(int val) :Sub1(val), Sub2(val){ cout << "Child含参构造函数" << endl; }
    31 };
    32 
    33 int main()
    34 {
    35     Child child(3);
    36     child.print();
    37 }

    输出结果:

    Base无参构造函数
    Sub1含参构造函数
    Sub2含参构造函数
    Child含参构造函数
    val = -858993460
    Press any key to continue . . .

    可见Sub1,和Sub2构造函数并没有执行Base的构造函数,虚继承的构造函数是这样的,先执行虚基类的无参构造函数,然后在执行Sub1的构造函数,在执行Sub2的构造函数,在执行Child的构造函数,并且在执行Sub1和Sub2的构造函数时并不再执行Base的构造函数。

    如果不用虚继承的访问方式:

     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 class Base
     6 {
     7 private:
     8     int val;
     9 public:
    10     Base(){ cout << "Base无参构造函数" << endl; };
    11     Base(int val){ this->val = val; cout << "Base有参构造函数" << endl; }
    12     void print(){ cout << "val = "<<val << endl; }
    13 };
    14 
    15 class Sub1 :public Base
    16 {
    17 public :
    18     Sub1(int val) :Base(val){ cout << "Sub1含参构造函数" << endl; };
    19 };
    20 
    21 class Sub2 :public Base
    22 {
    23 public:
    24     Sub2(int val) :Base(val){ cout << "Sub2含参构造函数" << endl; }
    25 };
    26 
    27 class Child :public Sub1, public Sub2
    28 {
    29 public :
    30     Child(int val) :Sub1(val), Sub2(val){ cout << "Child含参构造函数" << endl; }
    31 };
    32 
    33 int main()
    34 {
    35     Child child(3);
    36 
    37     //child.print()   //非法的访问
    38 
    39     child.Sub1::print();
    40     child.Sub2::print();
    41 }

    结果:

    Base有参构造函数
    Sub1含参构造函数
    Base有参构造函数
    Sub2含参构造函数
    Child含参构造函数
    val = 3
    val = 3
    Press any key to continue . . .

  • 相关阅读:
    4
    3
    iOS常用的三种支付方式
    iOS开发技术之银联支付
    iOS开发技术之支付宝支付
    iOS开发技术之微信支付
    Subversion使用总结
    如何在已有 Xcode 项目中 加入Cordova框架(或者称PhoneGap框架)进行iOS移动跨平台开发
    iOS开发中Masonry的使用总结:
    iOS开发中的权限适配问题总结
  • 原文地址:https://www.cnblogs.com/chaiwentao/p/4657339.html
Copyright © 2011-2022 走看看