C++中的继承-创新互联

继承的概念和定义 继承的概念

继承是面向对象程序设计使代码可以复用的重要手段,当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。

公司主营业务:成都做网站、成都网站制作、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。成都创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。成都创新互联推出中站免费做网站回馈大家。继承的定义 定义格式

在这里插入图片描述

继承父类成员访问关系的变化
类成员/继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的private成员派生类的private成员
基类的protect成员派生类的protected成员派生类的protected成员派生类的private成员
基类的private成员派生类中不可见派生类中不可见派生类中不可见
父类和子类的对象赋值转换
  1. 子类对象可以赋值给父类的对象/父类的指针/父类的引用。一般情况下子类对象都比父类对象大,这里赋值的时候会产生切片或者叫切割。
    切片/切割
    在这里插入图片描述

  2. 父类对象不能赋值给子类对象。但是指针和引用可以,但是必须进行强制类型转换,并且这个行为十分危险,可能存在越界访问。

class Person
{public:
	string _name;
};
class Student:public Person
{public:
	int _age;
	int _major;
};

int main()
{//子类可以赋值给父类
	Student a;
	Person b = a;
	Person* c = &a;
	Person& b = a;
	//父类不能赋值给子类
	a = b;
	//父类不能赋值给子类,但是可以进行强制转换
	Person* b1 = &b;
	Student* a1 = (Student*)b1;
	return 0;
}
继承中的作用域
  1. 在继承体系中父类和子类都有自己独立的作用域
  2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
子类的默认成员函数 默认成员函数
  1. 构造函数
  2. 析构函数
  3. 拷贝构造函数
  4. 赋值操作
原则

继承下来的调用父类处理,子类的按照普通类的基本规则。
那么什么情况下需要我们自己写?

  1. 父类没有默认构造,需要我们自己写默认构造
  2. 若子类没有资源需要释放,就需要我们自己显示的写析构函数
  3. 若子类存在深浅拷贝问题,就需要实现拷贝构造和赋值解决深浅拷贝问题
    如何写?
    父类成员调用父类对应的构造,拷贝构造,operator=和析构处理,自己成员按照普通类处理。
    析构函数的名称会被统一处理为destructor()
  4. 子类的析构函数和父类的析构函数会构成隐藏
  5. 子类的析构函数结束时会自动调用父类的析构函数
  6. 子类的析构函数不需要调用父类的析构函函数它会自动调用,这样才能保证先析构子类成员,再析构父类成员。
继承与友元

友元关系不能继承,就比如父亲的朋友不一定是你的朋友。

继承与静态成员

父类定义了static成员,则整个继承体系中只有一个这样的静态成员,无论派生出多少个子类,都只有一个static成员,因此静态成员可以继承下来,但是只有一份。

菱形继承以及菱形虚拟继承 单继承

一个子类只有一个直接父类时称这个继承关系为单继承。

多继承

一个子类有两个或者两个以上的直接父类时称这个继承关系为多继承。

菱形继承

菱形继承是多继承的一种特殊情况
在这里插入图片描述
当这样的继承关系出现的时候,对于Assistant会形成数据的冗余以及二义性,因为在其中出现了两份Person。
在这里插入图片描述
我们看下面一串代码,

在非虚继承中
#includeusing namespace std;

class A
{public:
	int _a;
};
class B : public A
//class B : virtual public A
{public:
	int _b;
};
class C : public A
//class C : virtual public A
{public:
	int _c;
};
class D : public B, public C
{public:
	int _d;
};
int main()
{D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
	return 0;
}

在这里插入图片描述
当我们查看d对象的地址,我们看到里面的存储是这样子存储的。并且是先继承谁先存储谁,倘若我们将代码中的D类换为

class D : public C, public B
{public:
	int _d;
};

在这里插入图片描述
我们要是将继承的顺序进行调换,那么我们将看到在d对象中就先存谁的顺序就会变换,先继承的先进行存储。

在虚继承中

当我们进行调试

  1. 首先创建了D对象在这里插入图片描述
  2. _a出现在这个位置在这里插入图片描述
  3. C中的_a将之前B中的_a进行了覆盖在这里插入图片描述
  4. 当我i们再观察内存发现_a存在一个公共的区域
    在这里插入图片描述
    我们发现当我们进行虚继承时是这样子进行存储的,A处在一个公共的区域,但是BC前面的东西还并不知道是什么
    在这里插入图片描述
    我们查看这里的地址,
    在这里插入图片描述
    发现这个地址里面记录着一个数字,这个数字就是B和C相对于公共成员A的偏移量/相对距离。
    此时这个A类一般称为虚基类,因为是虚继承下来的,在D里面,A存放在一个公共的区域,可能B,C都需要进行寻找A,这时候就通过虚基表中记录的偏移量来进行查找,这个BC之前的这个值就为虚基表的地址,虚基表中存储的就是偏移量,偏移量上面还有一个空间,既然为虚基表,表里面不会只存一个值,至于这个值具体是什么,在后面的多态进行讲。
继承和组合
  1. public继承是一种is-a的关系,也就是说每个子类对象都是一个父类对象。
  2. 组合是一种has-a的关系,假设B组合了A,那么每个B对象中都有一个A对象
  3. 优先使用组合而不是类继承。
    在这里插入图片描述

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站名称:C++中的继承-创新互联
文章URL:http://pwwzsj.com/article/diighd.html