C++中的继承和多继承
一、学习笔记
1.继承
class Student : public Person {
...
}
2.继承时权限
派生类中可以直接访问父类的protected成员,但是不能访问其private成员,若继承时不写public,默认就是private继承。
继承方式\基类中的访问属性 public protected private
public public protected 隔离
protected protected protected 隔离
private private private 隔离
(1) 无论哪种继承方式,在派生类的内部使用父类时并无差别
(2) 不同的继承方式,会影响这两方面:外部代码对派生类的使用,派生类的子类对派生类成员的使用。
3.using更改继承成员的权限
①修改成员变量的
在派生类中的public:下使用using Father::room_key;可以将父类的protected成员room_key提升为public权限,此时可以直接在main()中访问!
在派生类中的private:下使用using Father::room_key;可以将父类的protected成员room_key降低为private权限,此时就不可以在类外进行访问!
若在派生类中可以使用using关键字将父类的public成员降为private权限,这样子类的子类就继承不到这个属性了。
①修改成员函数的
在派生类中的public:下使用using Father::getRoomKey;可以将父类的protected成员getRoomKey()成员函数提升为public权限。可以直接使用函数名而不是
函数签名的原因是这里仅仅是修改权限,父类重载的所有getRoomKey()都变为public了,之后类外调用根据参数匹配规则不变。
也就是说可以使用using关键字调整继承来的成员的访问权限,但前提是这些成员对你这个类可见。
4.构造函数子类也会继承父类的,但是其构造的是从父类那里继承过来的部分。
5.子类中若是实现了与父类的同名函数getName(),可以Parent::getName()来调用父类的getName(), 但是操作的成员变量是子类继承父类的部分。
6.子类定义与继承来的可见的成员变量同名的成员变量也是可以的。重新定义函数签名和函数名都相同的函数叫做复写。
7.继承的父类的成员函数中操作的成员变量都是子类继承于父类的。父类的成员函数操作的成员变量都是父类的,除非子类进行了复写。
8.在子类的外部可以通过s1.Father::getRoomKey();调用父类的函数,在子类的内部可以通过Father::getRoomKey();调用父类的函数。
9.多重继承
class Sofabed: public Sofa, public Bed {
...
}
Sofabed s;
s::Sofa::setWeight() //指明调用Sofa的setWeight()
10.多继承会导致二义性,解决办法是使用虚继承。
解决:把共性的东西提炼出来,只保留一份备份,放在共有的父类Fourniture中,然后Sofa和Bed都虚继承Fourniture。
class Sofa : virtual public Fourniture
class Bed : virtual public Fourniture
class Sofabed: public Sofa, public Bed
11.虚继承内存分布
虚继承的成员在Sofabed类中只会保留一份备份,也就是说Fourniture类中定义的成员只会在SofaBed类中只保留一份。
12.要尽量避免使用多继承,它会使程序变得更加复杂,更容易出错。
13.带有继承和虚继承的构造函数的调用次序
先父后子:
(1)先调用基类的构造函数
①先调用虚拟基类的构造函数,再调用一般基类的构造函数。注意是先把所有虚基类的构造函数执行完后再执行的一般基类的构造函数。
(2)然后再调用自身的构造函数
①先调用对象成员的构造函数,然后再调用自己的构造函数。
对于虚继承的基类,基类的构造函数只执行一次。
eg: 如下两次继承,Furniture和Verication3C,它两个的构造函数是被调用一次!
class Soft : virtual public Furniture, virtual public Verication3C
class Bed : virtual public Furniture, virtual public Verication3C
14.子类的构造函数给父类的构造函数传参数
class LeftRightSofabed : public Sofabed, virtual public LeftRightCom {
private:
Date date;
public:
LeftRightSofabed(char *str1) : Sofabed(str1), LeftRightCom(str1), date(str1) { //注意这里的data用的是成员名,而不是类名
cout <<"LeftRightSofabed()"<<endl;
}
};
试验发现,在子类中使用初始化列表初始化虚继承的类无法触发虚继承的类中的有参构造函数被调用,调用的还是无参构造函数。
eg:上面代码中LeftRightCom()的有参构造函数不会被调用,调用的还是无参构造函数。
二、例子
1.单继承例子
#include <iostream>
using namespace std;
class Father {
private:
int money;
char *name;
protected:
int room_key;
int getRoomKey(int) {
cout << "getRoomKey(int) name=" << name << endl;
return room_key;
}
public:
int getRoomKey(void) {
cout << "getRoomKey(void) name=" << name << endl;
return room_key;
}
Father() {
money = ;
room_key = ;
name = "father_begin";
cout << "Father()" << endl;
}
Father(char *name) {
this->name = name;
cout << "Father(char *name)" << "name= " << this->name << endl;
}
~Father() {
cout << "~Father()" << endl;
}
int getMoney(void) {
cout << "int getMoney(void)" << endl;
return money;
}
void setMoney(int money) {
cout << "void setMoney(int money)" << endl;
this->money = money;
}
};
class Son : public Father {
char *name;
public:
using Father::room_key;
using Father::getRoomKey;
Son(char *name){
this->name = name;
cout << "Son()" << "name= " << this->name << endl;
}
~Son() {
cout << "~Son()" << "name= " << this->name << endl;
}
int getRoomKey(void) {
Father::getRoomKey();
cout << "getRoomKey(void) name=" << name << endl;
return room_key;
}
};
int main()
{
Son s1("son_name");
s1.getRoomKey();
s1.getRoomKey();
s1.Father::getRoomKey();
s1.getMoney();
cout <<"s1.room_key= "<< s1.room_key << endl;
return ;
}
/*
Father()
Son()name= son_name
getRoomKey(void) name=father_begin
getRoomKey(void) name=son_name
getRoomKey(int) name=father_begin
getRoomKey(void) name=father_begin
int getMoney(void)
s1.room_key= 1
~Son()name= son_name
~Father()
*/
2.多继承中使用虚继承来处理成员变量二义性问题
#include <iostream>
using namespace std;
class Furniture {
int weight;
public:
int size;
int getWeight() {
cout << "Furniture::getWeight()" << endl;
return weight;
}
};
class Sofa : virtual public Furniture {
int sofa;
public:
void getSofa() {
cout << "Sofa::getSofa()" << endl;
}
};
class Bed : virtual public Furniture {
int bed;
public:
void getBed() {
cout << "Bed::getBed()" << endl;
}
};
class Sofabed : public Sofa, public Bed {
int color;
public:
int getColor() {
cout << "Sofabed::getColor()" << endl;
return color;
}
int getSize() {
cout << "Sofabed::getSize()" << endl;
return size;
}
};
int main() {
Sofa so;
Bed be;
Sofabed sb;
so.getWeight();
so.getSofa();
be.getWeight();
be.getBed();
sb.getSize();
sb.getSofa();
sb.getBed();
sb.getWeight();
return ;
}
/*
Furniture::getWeight()
Sofa::getSofa()
Furniture::getWeight()
Bed::getBed()
Sofabed::getSize()
Sofa::getSofa()
Bed::getBed()
Furniture::getWeight()
*/
3.虚继承构造函数中调用父类构造函数的例子
#include <iostream>
using namespace std;
class Furniture {
public:
Furniture() {
cout << "Furniture()" << endl;
}
Furniture(char *abc) {
cout << "Furniture(abc)" << endl;
}
};
class Verication3C {
public:
Verication3C() {
cout << "Verication3C()" << endl;
}
Verication3C(char *abc) {
cout << "Verication3C(abc)" << endl;
}
};
class Soft : virtual public Furniture, virtual public Verication3C {
public:
Soft() {
cout << "Soft()" << endl;
}
Soft(char *abc) : Furniture(abc), Verication3C(abc) {
cout << "Soft(abc)" << endl;
}
};
class Bed : virtual public Furniture, virtual public Verication3C {
public:
Bed() {
cout << "Bed()" << endl;
}
Bed(char *abc) : Furniture(abc), Verication3C(abc){
cout << "Bed(abc)" << endl;
}
};
class SoftBed : public Soft, public Bed {
public:
SoftBed() {
cout << "SoftBed()" << endl;
}
SoftBed(char *abc) : Soft(abc), Bed(abc){
cout << "SoftBed(abc)" << endl;
}
};
class LeightWrightCom {
public:
LeightWrightCom() {
cout << "LeightWrightCom()" << endl;
}
LeightWrightCom(char *abc) {
cout << "LeightWrightCom(abc)" << endl;
}
};
class Type {
public:
Type() {
cout << "Type()" << endl;
}
Type(char *abc) {
cout << "Type(abc)" << endl;
}
};
class Date {
public:
Date() {
cout << "Date()" << endl;
}
Date(char *abc) {
cout << "Date(abc)" << endl;
}
};
class LeightWrightSofaBed : public SoftBed, virtual public LeightWrightCom {
Type type;
Date date;
public:
LeightWrightSofaBed() {
cout << "LeightWrightSofaBed()" << endl;
}
LeightWrightSofaBed(char *abc) : SoftBed(abc), LeightWrightCom(abc), type(abc), date(abc) {
cout << "LeightWrightSofaBed(abc)" << endl;
}
};
int main()
{
LeightWrightSofaBed l1("lll");
return ;
}
/*
Furniture() //没有调用有参构造函数!!
Verication3C() //没有调用有参构造函数!!
LeightWrightCom(abc) //调用了有参构造函数
Soft(abc)
Bed(abc)
SoftBed(abc)
Type(abc)
Date(abc)
LeightWrightSofaBed(abc)
*/
C++中的继承和多继承的更多相关文章
- C++中的多重继承与虚继承的问题
1.C++支持多重继承,但是一般情况下,建议使用单一继承. 类D继承自B类和C类,而B类和C类都继承自类A,因此出现下图所示情况: A A \ / B C ...
- HIbernate学习笔记(七) hibernate中的集合映射和继承映射
九. 集合映射 1. Set 2. List a) @OrderBy 注意:List与Set注解是一样的,就是把Set更改为List就可以了 private List< ...
- JS中通过call方法实现继承
原文:JS中通过call方法实现继承 讲解都写在注释里面了,有不对的地方请拍砖,谢谢! <html xmlns="http://www.w3.org/1999/xhtml"& ...
- Java中的集合类型的继承关系图
Java中的集合类型的继承关系图
- 盘点CSS中可以和不可以继承的属性
CSS中可以和不可以继承的属性 一.无继承性的属性 1.display:规定元素应该生成的框的类型 2.文本属性: vertical-align:垂直文本对齐 text-decoration:规定 ...
- 对Java中多态,封装,继承的认识(重要)
一.Java面向对象编程有三大特性:封装,继承,多态 在了解多态之前我觉得应该先了解一下 ...
- oc中protocol、category和继承的区别
OC中protocol.category和继承的区别以前还是有点迷糊,面试的时候说的有点混乱,现在结合一些资料总结一下. 利用继承,多态是一个很好的保持"对扩展开放.对更改封闭"( ...
- C++ 中私有继承、保护继承与公有继承
区别 下面通过一个示例来介绍三种继承的区别. 定义一个基类(假设为一个快退休的富豪): class RichMan { public: RichMan(); ~RichMan(); int m_com ...
- js中的对象创建与继承
对象创建 1.工厂模式 优点:解决了创建多个相似对象的问题 缺点:没有解决对象识别问题:每一个对象都有一套自己的函数,浪费资源 function createPerson(name, age, job ...
- Es5中的类和静态方法 继承
Es5中的类和静态方法 继承(原型链继承.对象冒充继承.原型链+对象冒充组合继承) // es5里面的类 //1.最简单的类 // function Person(){ // this.name='张 ...
随机推荐
- Xilinx FPGA复位逻辑处理小结(转)
Xilinx FPGA复位逻辑处理小结 1. 为什么要复位呢? (1)FPGA上电的时候对设计进行初始化: (2)使用一个外部管脚来实现全局复位,复位作为一个同步信号将所有存储单元设置为一个已知的状态 ...
- CentOS7安装配置Bacular
参考: http://blog.51cto.com/molewan/2045602 https://blog.csdn.net/heshangkung/article/details/47955023 ...
- 界面控件DevExpress发布v18.2.5|附下载
DevExpress Universal Subscription(又名DevExpress宇宙版或DXperience Universal Suite)是全球使用广泛的.NET用户界面控件套包,De ...
- 设置table中的td一连串内容自动换行
遇到一长串字母撑出了td宽度,导致整个表格错乱,如图: , 解决办法: 第一: table 加上css: table-layout: fixed;(此css属性 表示 列宽由表格宽度和列宽度设定.不会 ...
- iframe 常见问题 解析
1. jquery在iframe子页面获取父页面元素代码如下: $("#objid",parent.document) 2. jquery在父页面获取iframe子页面的元素代码如 ...
- Day15作业及默写
1.整理今天内容 PASS 2.现有列表alist = [3,1,-4,2,-6] 按照元素的绝对值大小进行排序 alist = [3,1,-4,2,-6] sorted(alist,key=lamb ...
- 键盘keycode对照表
- python 应用 pyamg
paper idea要用到pyamg,虽然这个包只有几行代码,但是还是折磨了我挺久,配置环境什么的就废了挺多时间. 好久没用pyamg了,然后又换了电脑,突然感觉有点方,,都忘了之前怎么弄的,今天运行 ...
- Semaphore计数信号量
ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semp = new Semaphore(5); for ...
- cxf动态调用外部web service 报告异常java.lang.NoSuchFieldErr
原因:cxf 依赖的xmlschema-core 与axis2-kernel依赖的xmlschema冲突. 解决方法:因为在项目中只用cxf即可,所以删除axis2的依赖.