前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c++那些事儿3.0 继承

c++那些事儿3.0 继承

作者头像
热心的社会主义接班人
发布2018-04-27 13:07:53
5860
发布2018-04-27 13:07:53
举报
文章被收录于专栏:cs
代码语言:javascript
复制
    一般形式   
     class class_name:继承方式 基类名{ code   }
         继承方式有三种: public ,protected,private.   //java好像都是public继承。
     单继承
     多继承,多继承会很复杂,所以java,c sharp都采用interface。
  类函数:
     构造函数
           先执行父类的构造函数,在执行子类的构造函数。
           一般形式  派生类的构造函数(参数列表):基类构造函数名(参数列表}{ code}
     析构函数
           先构造的后析构,后构造的先析构。
     虚函数。
     避免二义性。但是最后的派生类不仅负责对直接基类初始化,还要对虚基类初始化。

看code是最有用的,细节情况已经注释说明。


代码语言:javascript
复制
#include<iostream>
#include<string>
using namespace std;
     // 类A
class A {
  protected:
    string name;
    int id;
    double da;
private:
    double pa; //这个数据继承后不能被访问
 public:
     A(string name, int id) {
         cout << "A的构造函数执行"<<endl;
         this->name = name;   //this指针
         this->id = id;
         this->da = da;
     }

     void setDa(double d) {
         da = d;
     }

     ~A() {
         cout << "A的析构函数"<<endl;
     }

    void setId(int id) {
//id是私有数据成员,不能被继承,类外不能访问,通过函数才能
        this->id = id;
     }

     void print() {
         cout << "string=" << name << "  " << "id=" << id<< endl;
     }

};
// 注意 C++中类的结尾是有;的,和java不同,我vs,ide编辑没有在意。

//如果不写关键字,默认为private。
class B :virtual public A {
    //B类public继承A类,但是私有数据成员不能访问。
  protected:
    int id;  //A类的id成员被覆盖了。

  public:
  /*
  父类构造函数的初始化通过子类构造函数初始化列表实现,
  */
    
      B(string na,int ida,int idb):A(na,ida){
          cout << "B的构造函数执行"<<endl;
          this->id = idb;
      }
      ~B() {
          cout << "B的析构函数"<<endl;
      }

      void  print() {
          /*
          基类同名的数据成员在派生类被覆盖,成为不可见。
          */
          cout << "A类被继承的ID:" << A::id << endl;
          cout <<"name:B"<< name<<" "<<"id:"<<id<<endl; //name是继承A的。
      }

};

class C:virtual public A{

    //B类public继承A类,但是私有数据成员不能访问。
protected:
    int id; 

public:
    /*
    父类构造函数的初始化通过子类构造函数初始化列表实现,
    */
    C(string na,int ida,int idc) :A(na,ida) {
        cout << "C的构造函数执行" << endl;
        this->id = idc;
    }
    ~C() {
        cout << "C的析构函数" << endl;
    }

    void  print() {
        cout << "name:C" << name << " " << "id:" << id << endl;; //name是继承A的。
        
    }
};

//D类继承B,C, 因为B,C都继承A,所以D类有2份A,这样就会出现二义性问题。
class D :public B,public C {
 public:
     void showId() {
        /* cout << "id::" << id << endl;
           如果这样,就会产生二义性,D公有继承了B,C protedted的id,
           这里不知道访问哪一个。 但是可以通过域运算符指定A,B,C继承来的id。
        */
         cout << "id::A" <<A::id << endl;
                  //通过域运算符指定id。
     }

     /*
      D继承了,B,C。B,C继承了A,即继承了double da;
      怎么访问它了。
          cout<<da;
          cout<<A::da; 都不行,无法指出是继承B的,还是C的。
           所以就要虚基类了。
     */
     void showDa() {

         cout << "B::da" << B::da << endl;
     }
     /*
     在以前派生类只对其直接基类初始化,在由其直接子类对间接子类初始化
     现在由于虚基类在派生类只有一份拷贝,所以这份数据必须由派生类给出。
     因为类B,类C可能给出不同的构造函数,这样对虚基类初始化会产生矛盾。
     */

     D(string na, int ida, int idc) :C(na, ida, idc),
         B(na, ida, idc), A(na, ida)
     {
         cout << "D的构造函数执行" << endl;
     }
     ~D() {
         cout << "D的析构函数" << endl;
     }

 
};

int main() {


    A a("name_A", 111);
    a.print();
    cout << "-----------------------------" << endl;
    //先执行父类的构造函数,在执行基类的构造函数
    B b("name_B",111, 222);
    //这里是B的id,因为private属性在子类不能访问。
    b.print();
    cout << "-----------------------------" << endl;
    C c("name_C", 111, 333);
    //这里是B的id,因为private属性在子类不能访问。
    c.print();
    cout << "-----------------------------" << endl;


    D d("name_D", 111, 444);

    // id的二义性 可以通过 ::域运算符指定,解决。
       d.showId();

     // 准备验证double da; 产生二义性的情况,这个就只能通过虚基类确定。
      //   setDa() 是会产生二义性的函数,但是A是虚基类。
       d.setDa(3.1415926);
       d.showDa();
       cout << "-----------------------------" << endl;

    
     system("pause");  //vs要看析构函数要去掉这一句。
    return 0;
}

结果如下,可以对照代码分析

 结果图.PNG
结果图.PNG

这里main函数的代码如下:

代码语言:javascript
复制
int main() {
       D d("name_D", 111, 444);
    // id的二义性 可以通过 ::域运算符指定,解决。
       d.showId();

     // 准备验证double da; 产生二义性的情况,这个就只能通过虚基类确定。
      //   setDa() 是会产生二义性的函数,但是A是虚基类。
       d.setDa(3.1415926);
       d.showDa();
       cout << "-----------------------------" << endl;

                                     /*  vs选择开始执行但不调试 */
    // system("pause");  //vs要看析构函数要去掉这一句。
    return 0;
}

构造函数和析构函数执行顺序验证

 只保留了D类.PNG
只保留了D类.PNG

东西好多啊,c++ 讲个语法就不少东西了

虚函数,多态性,这个代码挖了坑,后面在讲,好累啊。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.09.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档