C++基础:继承

继承

类之间的关系:包含、使用、继承

(1)简单使用

class Parent
{
public:
	void print()
	{
		cout << "a: " << a << "b: " << b << endl;
	}
private:
	int a;
	int b;
};

//class Child : private Parent
//class Child : protected Parent
class Child : public Parent
{
private:
	int c;
};

void main()
{
	Child c1;
	system("pause");
}
  1. 子类拥有父类的所有成员变量和成员函数;

  2. 子类可以拥有父类没有的方法和属性 ;

  3. 子类就是一种特殊的父类 ;

  4. 子类对象可以当作父类对象使用 ;

(2)派生类的访问控制

  1. C++中的继承方式会影响子类的对外访问属性:

public继承:父类成员 在 子类 中保持原有访问级别;

private继承:父类成员 在 子类 中变成private成员;

protected继承:父类中 public 成员会变成 protected;父类中 protected 仍然是;private仍然是;

  1. 判断子类的对外访问属性

看调用语句,在子类的内部还是外部;

看子类如何从父类继承;

看父类中的访问级别;

(3)继承中的构造和析构

  1. 类型兼容性

子类就是特殊的父类 (base *p = &child);

父类 指针(引用)指向 子类对象:Parent *p = &chile;

子类指针做函数父类参数;printP(&chile);

子类引用做函数父类参数;printP(chile);

子类对象 初始化 父类对象;Parent p = chile;

  1. 继承中的对象模型

类在C++编译器的内部可以理解成结构体,子类是由父类成员叠加子类新成员得到的;

objA: | objA.x | objA.y | -->

objB: | objB.x | objB.y | objB.s |-->

objC: | objC.x | objC.y | objC.s | objC.n | objC.m |

  1. 父类与子类的构造函数有什么关系

在子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化;

在子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理;

  1. 继承中的构造析构调用原则
// 创建子类对象  -->  首先调用父类的构造函数  -->  再执行子类的构造函数
Child c1(1, 2, 3);
// 当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
Child(int a, int b, int c) : Parent(a, b);
// 析构函数调用的先后顺序与构造函数相反 
  1. 继承与组合混搭情况下,构造和析构调用原则

先构造父类,再构造成员变量(组合对象变量)、最后构造自己;

先析构自己,在析构成员变量(组合对象变量)、最后析构父类

  1. 继承中的同名成员变量处理方法

当子类成员变量与父类成员变量同名时,子类依旧从父类继承同名成员 ;

在子类中通过作用域分辨符::进行同名成员区分(在派生类中使用基类的同名成员,显式地使用类名限定符);

同名成员存储在内存中的不同位置 ;

  1. 子类中的 static 关键字

基类定义的静态成员,将被所有派生类共享;

static 成员遵守派生类的访问控制

子类访问静态成员:类名::成员; 对象名.成员

注意:

class Parent
{
public:
	static int i;
}
int Parent::i = 100;
// 初始化静态成员,并为静态成员分配内存! 才能给子类使用

(4)多继承

  1. 多继承

一个类有多个直接基类的继承关系称为多继承

class child : public Base1, public Base2

  1. 虚继承

多继承二义性原因:

如果一个子类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的名字进行访问时,可能产生二义性

class B {public: int b;};

class B1 : public B {public: int b1;};
class B2 : public B {public: int b2;};

class C : public B1, public B2
{
public:
    int c;
}

void test()
{
    C c;
    c.B; //err	无法判断B从哪里继承
}

多继承二义性解决:

// 虚继承 virtual
class B1 : virtual public B {public: int b1;};
class B2 : virtual public B {public: int b2;};
// 使用虚继承后,基类B的构造函数只调用了一次
//可以判断在子类C定义的对象,内存模型中B1、B2共有一份B。。。

(5)总结

  1. 继承是面向对象程序设计实现软件重用的重要方法。程序员可以在已有基类的基础上定义新的派生类。
  2. 派生类对基类成员的访问由继承方式和成员性质决定。
  3. 创建派生类对象时,先调用基类构造函数初始化派生类中的基类成员。调用析构函数的次序和调用构造函数的次序相反。
  4. C++提供虚继承机制,防止类继承关系中成员访问的二义性。

猜你喜欢

转载自www.cnblogs.com/2dx3906/p/13173372.html
今日推荐