C++继承
2016-06-15 16:18
337 查看
继承(inheritance)机制是 面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能 。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。
继承定义格式
example:
class teacher:public people
基类成员在派生类的可见性:
class A
{
public :
void fun1();
int k1;
protected :
int m1;
private :
int n2;
};
class B :public A
{
public :
void fun2();
int k2;
protected :
int m2;
private :
int n3;
};
公有继承时;
派生类的成员函数可以访问基类的公有成员和保护成员;
即 在函数fun2内部可以有 m1;
派生类的对象只可以访问基类的公有成员;
如 B b1; b1.k1;(正确) b1.m1;(不可以访问);
在继承关系里面,在派生类中如果没有显示定义六个默认成员函数,编译系统则会默认合成这6个默认的成员函数。
【继承关系中构造函数调用顺序】
【说明】
1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。
【继承关系中析构函数调用过程】
继承体系中的作用域
1. 在继承体系中基类和派生类是两个不同作用域。
2. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类 ::基类成员 访问)
即同名隐藏,另外子类和父类有同名成员函数,子类的对象在调用时不会调用父类的成员函数,要想调用父类成员函数,需要 对象.父类::成员函数名…的方式调用;
3. 注意在实际中在继承体系里面最好不要定义同名的成员
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
构造函数不能被继承,因此派生类的构造函数必须先调用基类的构造函数来初始化基类的数据成员;
析构函数不能被继承,析构时先执行派生类的析构函数,再执行基类的析构函数,顺序和执行构造函数时读顺序相反。
基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。
【赋值兼容规则】
1. 子类对象可以赋值给父类对象(切割/切片);
2. 父类对象不能赋值给子类对象;
3. 父类的指针/引用可以指向子类对象;
4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成);
5.派生类对象的地址值可以赋给基类的对象指针;
6.派生类对象可以用来给基类对象引用初始化;
【继承方式】
单继承:每个类可以生成多个派生类,但每个派生类只能有一个基类;类似于树;
多继承:派生类具有多个基类;class C:public B,public A{};
派生类构造函数执行顺序是先执行所有的基类的构造函数,再执行派生类本身的构造函数;处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构造函数中定义的成员的初始化列表的各项顺序无关;
【多继承的二义性问题】
1.派生类的多个基类中具有同名成员;
采用作用域运算符限定可以解决,或者在派生类内定义同名成员来屏蔽。
2.多个派生类有共同基类时;访问公共基类的成员;
一般出现在菱形继承:
在Assistant中访问一个Person类中的公有继承成员时;
Assitant t1;
t1.a; t1.person::a; 都具有二义性;
这时 :sizeof(Assitant)=20; 4+4+4+4+4=20;
t1.student::a; t1.teacher::a; 是正确的;
为了彻底避免这种继承机构中的二义性,引入虚基类。
【虚基类】
virtual <继承方式> <基类名>
声明为虚基类后,在菱形继承中,只调用一次基类的构造函数;
这时:sizeof(Assitant )=24;
这时 t1.person::a;就没有二义性了;
继承定义格式
example:
class teacher:public people
基类成员在派生类的可见性:
class A
{
public :
void fun1();
int k1;
protected :
int m1;
private :
int n2;
};
class B :public A
{
public :
void fun2();
int k2;
protected :
int m2;
private :
int n3;
};
公有继承时;
派生类的成员函数可以访问基类的公有成员和保护成员;
即 在函数fun2内部可以有 m1;
派生类的对象只可以访问基类的公有成员;
如 B b1; b1.k1;(正确) b1.m1;(不可以访问);
在继承关系里面,在派生类中如果没有显示定义六个默认成员函数,编译系统则会默认合成这6个默认的成员函数。
【继承关系中构造函数调用顺序】
【说明】
1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。
【继承关系中析构函数调用过程】
继承体系中的作用域
1. 在继承体系中基类和派生类是两个不同作用域。
2. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类 ::基类成员 访问)
即同名隐藏,另外子类和父类有同名成员函数,子类的对象在调用时不会调用父类的成员函数,要想调用父类成员函数,需要 对象.父类::成员函数名…的方式调用;
3. 注意在实际中在继承体系里面最好不要定义同名的成员
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
构造函数不能被继承,因此派生类的构造函数必须先调用基类的构造函数来初始化基类的数据成员;
析构函数不能被继承,析构时先执行派生类的析构函数,再执行基类的析构函数,顺序和执行构造函数时读顺序相反。
基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。
【赋值兼容规则】
1. 子类对象可以赋值给父类对象(切割/切片);
2. 父类对象不能赋值给子类对象;
3. 父类的指针/引用可以指向子类对象;
4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成);
5.派生类对象的地址值可以赋给基类的对象指针;
6.派生类对象可以用来给基类对象引用初始化;
【继承方式】
单继承:每个类可以生成多个派生类,但每个派生类只能有一个基类;类似于树;
多继承:派生类具有多个基类;class C:public B,public A{};
派生类构造函数执行顺序是先执行所有的基类的构造函数,再执行派生类本身的构造函数;处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构造函数中定义的成员的初始化列表的各项顺序无关;
【多继承的二义性问题】
1.派生类的多个基类中具有同名成员;
采用作用域运算符限定可以解决,或者在派生类内定义同名成员来屏蔽。
2.多个派生类有共同基类时;访问公共基类的成员;
一般出现在菱形继承:
在Assistant中访问一个Person类中的公有继承成员时;
Assitant t1;
t1.a; t1.person::a; 都具有二义性;
这时 :sizeof(Assitant)=20; 4+4+4+4+4=20;
t1.student::a; t1.teacher::a; 是正确的;
为了彻底避免这种继承机构中的二义性,引入虚基类。
【虚基类】
virtual <继承方式> <基类名>
声明为虚基类后,在菱形继承中,只调用一次基类的构造函数;
这时:sizeof(Assitant )=24;
这时 t1.person::a;就没有二义性了;
相关文章推荐
- CString与char *互转总结
- C++ 函数的扩展②
- 微视图像(microview)gige相机开发手记(2)
- CString,string,char*之间的转换
- C++中的继承
- Effective C++ 笔记2(构造,析构,赋值)
- [leetcode] 【字符串】 38. Count and Say
- C++ 函数的扩展①
- C++ vector和list的区别
- [leetcode] 【字符串】13. Roman to Integer
- C语言三种预处理功能
- C++中关于全局对象的初始化顺序
- memset
- C++程序设计语言练习7.9 迭代器的使用
- C—文件操作
- C++中引用(&)的用法和应用实例
- C语言反转单链表
- HDOJ 2011 多项式求和
- C++primer函数引用形参 左值和右值d额
- C++实践参考——人数不定的工资类