C++之继承
基类中的构造函数和析构函数不能被继承,在派生类中需要定义新的构造函数和析构函数,私有成员不能被继承。对象访问在派生类外部,通过派生类的对象对从基类继承来的成员的访问。
1、类与类之间的关系有哪些?
与类之间的关系分为纵向和横向两种:
纵向就是继承;横向包括:依赖、关联、聚合和组合。(这里不进行解释,详解链接:https://blog.csdn.net/u014694510/article/details/88316605.
2、什么是继承?继承有什么作用?
所谓继承就是从先辈出得到属性和行为特征。类的继承就是新的类从已有类那里得到已有的特征;从另一个角度来看,类的继承和派生机制使程序员无需修改已有类,只需在此类的基础上,通过少量代码或修改少量代码的方法得到新的类,从而很好的解决了代码重用的问题。由已有类产生新类时,新类便包含了已有类的特征,同时也可以加入自己的新特征。已有类被称为基类或者父类,产生的新类被称为派生类或者子类。
3、继承有哪些分类?
派生类的继承方式有私有继承(private),公有继承(public),保护继承(protect)
4、基类成员在派生类的访问属性是怎样的?
基类中的成员 | 在公有派生类的访问属性 | 在私有派生类中的访问属性 | 在保护派生类中的访问属性 |
---|---|---|---|
私有成员 | 不可直接访问 | 不可直接访问 | 不可直接访问 |
公有成员 | 公有 | 私有 | 保护 |
保护成员 | 保护 | 私有 | 保护 |
5、基类的成员函数都能被继承吗?
不是。基类中的构造函数和析构函数不能被继承,在派生类中需要定义新的构造函数和析构函数,私有成员不能被继承。
6、派生类对基类成员的访问规则是怎样的?
内部访问:由派生类中新增的成员函数对基类继承来的成员的访问。
对象访问:在派生类外部,通过派生类的对象对从基类继承来的成员的访问。
私有继承的访问规则:
基类中的成员 | 私有成员 | 公有成员 | 保护成员 |
---|---|---|---|
内部访问 | 不可访问 | 可访问 | 可访问 |
对象访问 | 不可访问 | 不可访问 | 不可访问 |
公有继承的访问规则:
基类中的成员 | 私有成员 | 公有成员 | 保护成员 |
---|---|---|---|
内部访问 | 不可访问 | 可访问 | 可访问 |
对象访问 | 不可访问 | 可访问 | 不可访问 |
保护成员的访问规则:
基类中的成员 | 私有成员 | 公有成员 | 保护成员 |
---|---|---|---|
内部访问 | 不可访问 | 可访问 | 可访问 |
对象访问 | 不可访问 | 不可访问 | 不可访问 |
先看个简单的代码了解一下:
class Person{public: void work() { cout public: void show() { cout cout public: void show() { cout _name=name; _age=age; _sex=sex; _wife=wife; } ~Person() { cout cout cout public: Student(string name, int age, string sex, string num, string wife = string()) :Person(name,age,sex,wife) { cout Student s("zjh",11,"man","1111"); s.show();}
错误原因:C++规定,当基类的构造函数没有参数,或没有显示定义构造函数时,派生类可以不向基类传递参数,甚至可以不定义构造函数。当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供把参数传递给构造函数的途径。
7、派生类构造函数和析构函数的执行顺序是怎样的?
通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数;当撤销派生类对象时,则先执行派生类的析构函数,随后再执行基类的析构函数。
8、派生类构造函数的参数列表是怎样构成的?
Student(string name, int age, string sex, string num, string wife = string()) :Person(name,age,sex,wife)
从上面列出的派生类Student
构造函数首行中可以看到,派生类构造函数名后边括号内的总参数表中包括了参数的类型和参数名,而基类构造函数参数表中只有参数名而不包括参数类型,因为在这里不是定义基类构造函数,而是调用基类构造函数
(这里的调用和在主函数中的调用是一样的,只是为了说明这部分参数需要用基类的构造函数初始化),因此这些参数是实参而不是形参。它们可以是派生类构造函数总参数列表中的参数,也可以是常量和全局变量。
9、如果有多层继承,参数列表又怎样构成?
这里我们给上边的Student
类再写一个派生类来看看
class High_Student :public Student{public: High_Student(string name, int age, string sex, string num, string high, string wife = string()) :Student(name, age, sex, num,wife) { cout High_Student a = { "zjh",21,"nan","1010","sss","aaa"}; a.eat(); return 0;}
我们可以看出,这里依旧是类名后边是总参数列表,但是冒号后边是前两个父类的实参,我们可以将Student(name, age, sex, num,wife)
理解为嵌套调用,即执行该语句之后,还是先调用Person
类的构造函数初始化name、sge、sex、wife
四个参数,再调用Student
类的构造函数初始化num
.
10、C++中的隐藏是怎样的?
还是先看代码:
class Base{public: void fun1(int a) { cout fun1(10);//这里会报错 cout Derive d; d.fun1(10);//这里会报错,显示没有匹配的函数}
问题:明明子类继承了父类只有一个参数的构造函数,为什么还不能用?
C++中规定,当父类和子类有同名参数时,子类会隐藏父类的同名函数,导致子类对象和子类成员函数不能调用。
解决办法:d.Base::fun1();
Base::fun1()
给函数加作用域
接下来我们再看一段代码,通过这段代码引出虚基类的概念:
class Base{public: Base() { a = 5; cout a = a + 10; cout a = a + 20; cout coutpublic: Base() { a = 5; cout a = a + 10; cout a = a + 20; cout cout