C++ 继承和派生

来源:互联网 发布:dm1016破解网络锁 编辑:程序博客网 时间:2024/05/27 14:12
  • 派生
    • 派生类是基类的具体化,而基类是派生类的抽象
    • 派生类的定义:
      • class 派生类名: [继承方式] 基类名
      • { 派生类新增加的成员 };
    • 派生类中声明一个与基类成员相同的成员或者成员函数,会覆盖对应基类的成员或者成员函数


  • 继承的方式:
    • (1) 公共继承(public):
      • 公用基类成员在公用派生类中的访问属性(私有->不可访问;公用成员->公用;保护成员->保护)
      • 对于基类私有变量只能通过基类的公用成员函数访问,比如stud1.display()。
    • (2) 私有继承(private):
      • 公用基类成员在公用派生类中的访问属性(私有->不可访问;公用成员->私有;保护成员->私有),
      • 不能访问基类的私有数据成员。对新加入的私有成员和函数,只能在派生类内部调用。
    • (3) 受保护的继承(protected):
      • 公用基类成员在公用派生类中的访问属性(私有->不可访问;公用成员->保护;保护成员->保护),
      • 不能访问基类的私有数据成员。对新加入的私有成员和函数,只能在派生类内部调用。(在内部相当于是私有的,但是在下层公用派生类中可以被访问。)

  • 派生类的构造函数
    • (1) 派生类构造函数名(总参数列表) : 基类构造函数名(参数列表) {派生类中新增数据成员初始化语句},例如
      •  Student1 (int n, string nam, char s, int a, sting ad): Student(n, nam, s)   // 注意顺序
      • 或者Student1 (int n, string nam, char s, int a, sting ad): Student(n, nam, s), age(a), addr(ad) {}
    • (2) 有子对象的派生类构造函数:
      • 派生类构造函数名(总参数列表) : 基类构造函数名(参数列表), 子对象名(参数列表) {派生类中新增数据成员初始化语句}
      • Student1 (int n, string nam, int n1, string nam1, int a, sting ad): Student(n, nam, s), monitor(n1, nam1) {}
    • (3) 派生类构造函数调用顺序: 基类构造函数 -> 子对象构造函数 -> 派生类构造函数;
    • (4) 派生类析构函数调用顺序: 派生类析构函数 -> 子对象析构函数 -> 基类析构函数

  • 多重继承  
    • (1) class D: public A, private B, protected C    {类D新增加的成员}   // 调用构造函数A->B->C->D
    • (2) 如果基类中有同名变量,解决二义性的方式就是用当前类的名字来限定,比如Teacher::name. 对于同名函数,如果没有改变,相当于覆盖。
      • C继承A,B类,每个类中都含同名变量a,C c;解决二义性的方法: c.a,c.A::a,c.B::a;
    • (3) 多重继承引起的二义性:用基类的名来限定,C c1; c1.A::a=3; c1.A::display();    //注意一定明确变量和函数的继承关系。

  • 虚基类:解决同名函数,节省空间,避免二义性
    • (1) 虚基类的一般形式:class 派生类名:virtual 继承关系 基类名
    • (2) 虚基类的初始化(P381):class D: public B, public C {D(int n):A(n), B(n), C(n) {};}  // A为基类,B,C为A的派生类
    • (3) 在派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化    //编译系统只执行最后的派生类对虚基类的构造函数的调用,而忽略其他派生类的调用。

  • 基类和派生类的转换 (只有公用派生类才是基类真正的子类型,“大材小用”原则) 
    • A a1; B b1;  // A是基类,B是A的派生类 
  • (1) 派生类对象可以向基类对象赋值,例如
    • a1 = b1;    // 单向不可逆
  • (2) 派生类对象可以初始化基类的引用
    • A &r = b1;  // r并不是b1的别名,而是与b1共享一段存储单元。换句话说是b1基类部分的别名
  • (3) 指向基类的指针可以指向派生类
    • A *p = &b1;    // p指向的是b1从基类继承的部分