简单对继承总结

来源:互联网 发布:网页文字游戏源码 编辑:程序博客网 时间:2024/05/23 18:47

继承
继承通俗的说便是是代码复用,子类复用父类的原有特性,并且自己在进行扩展,增加功能。
一.基础知识
1.格式如下:
class childname::继承类型 fathername
{}

2、访问限定符:
public(公有继承)、protected(保护继承)、private(私有继承)
继承方式 基类的public 基类的protected 基类的private 继承引起的访问控制关系变化概括
public继承 仍为public成员 变为protected成员 不可见 基类的非私有成员在子类的访问属性都不变
protected继承 仍为protected成员 变为protected成员 不可见 基类的非私有成员在子类的保护成员
private继承 仍为private成员 变为private成员 不可见 基类的非私有成员在子类的私有成员
总结:
a) 基类的私有成员在子类中是不可被访问的;如果基类成员不想被除了子类外访问的话,可定义为保护成员;
b) 每个子类对象都是父类的对象(子类中继承父类的成员);
c) class默认是私有继承,struct默认是public;
d) 如果在派生类中没有显示定义这六大函数,则编译系统会自动合成这六个默认的函数;
3、继承关系中构造函数调用顺序和输出顺序
调用顺序:派生类构造函数 ——-基类构造函数 ——派生类构造函数体
输出顺序:基类构造函数 —-派生类构造函数
基类构造函数函数体执行顺序比派生类构造函数函数体执行早;
4、说明:
a) 基类没有缺省构造函数,派生类必须要在初始化列表中显示地给出基类名和参数列表;
a) 例如: Base(int a)
b) 基类没有定义构造函数,则派生类也可以不定义,全部使用缺省构造函数;
c) 基类定义了带有形参的构造函数,派生类就一定要定义构造函数;
5、继承体系的作用域
a) 在继承关系中基类和派生类不是一个作用域;
b) 基类和派生类中有同名成员变量是,派生类成员变量会覆盖基类成员变量;
基类和派生类中有同名成员函数时,派生类成员变量会屏蔽基类对成员的直接访问;
(在派生类成员函数中可以使用“基类::基类成员”访问)
c) 最好不要定义同名成员;
class Person
{
public:
Person( const char * name = “” , int id = 0): _name(name ), _num( id){}
protected:
string _name; // 姓名
int _num; // 身份证号
};
class Student: public Person
{
public :
Student(const char * name, int id, int stuNum): Person(name , id ), _num(stuNum ){}
void DisplayNum()
{
cout<<” 身份证号:” < < Person :: _num<< endl ;
cout<<” 学号”<< _num << endl ;
}
protected :
int _num ; // 学号
};
6.继承与转换–赋值兼容规则–public继承
1. 子类对象可以赋值给父类对象(切割/切片)–>赋值的那部分是子类继承父类的部分
2. 父类对象不能赋值给子类对象–>程序会崩溃
3. 父类的指针/引用可以指向子类对象
4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)
7、友元与继承
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
class Person
{
friend void Display(Person &p , Student&s);
protected :
string _name ; // 姓名
};
class Student: public Person
{
protected :
int _stuNum ; // 学号
};
void Display(Person &p , Student &s)
{
cout < < p._name < < endl;
cout < < s._name < < endl;
cout < < s._stuNum < < endl;
}
void TestPerson1()
{
Person p;
Student s;
Display (p, s);
}
8、继承与静态成员
基类定义了static成员(可以被继承),则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。
class Person
{
public :
Person()
{
++ _count;
}
protected :
string _name ; // 姓名
public :
static int _count; // 统计人的个数。
};
int Person::_count = 0;
class Student : public Person
{
protected :
int _stuNum ; // 学号
};
class Graduate :public Student
{
protected:
string _seminarCourse; // 研究科目
};
void TestPerson1()
{
Student s1;
Student s2;
Student s3;
Graduate s4;
cout < < “人数:” < < Person::_count < < endl;
Student ::_count = 0;
cout < < ”人数:” < < Person::_count < < endl;
}
二、继承种类:单继承、多继承、菱形继承
1、单继承:一个子类只有一个直接父类时称这个继承关系为单继承。
存储时,先是基类成员再是派生类自己的成员
2.多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承–>先继承的对象的最前面(存储时,先是多个基类成员从先到后再是派生类自己的成员)
3、菱形继承
class Person
{
public :
string _name ; // 姓名
};
class Student : public Person
{
protected :
int _num ; //学号
};
class Teacher : public Person
{
protected :
int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
string _majorCourse ; // 主修课程
};
void Test ()
{// 显示指定访问哪个父类的成员
Assistant a ;
a.Student ::_name = “xxx”; //对象.类名::数据成员
a.Teacher ::_name = “yyy”;
}
虚继承–解决菱形继承的二义性和数据冗余的问题
1. 虚继承解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余&浪费空间的问题。
2. 虚继承体系看起来好复杂,在实际应用我们通常不会定义如此复杂的继承体系。一般不到万不得已都不要定义菱形结构的虚继承体系结构,因为使用虚继承解决数据冗余问题也带来了性能上的损耗。

0 0