1、继承的概念和定义
2、基类与派生类对象的赋值转换(切片)
3、继承中的作用域、隐藏
4、派生类的默认成员函数
5、继承与友元、继承与静态成员
6、多继承
1、继承的概念和定义
继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类的特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。
继承的定义格式:
class Student : public Person //Student是派生类,public是继承方式,Person是基类
{
pubilc:
int _stuid;
int _major;
};
继承基类成员访问方式的变化:
类成员/继承方式 | pubilc继承 | protected继承 | private继承 |
基类的public成员 | 派生类的public成员 | 派生类的protected 成员 | 派生类的private成员 |
基类的protected成员 | 派生类的protected 成员 | 派生类的protected成员 | 派生类的private成员 |
基类的private成员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可见 |
总结:
1、基类的私有成员在派生类中都是不可见的
2、一般实际运用时都是public继承,这样才可以很好的利用继承所实现的复用功能
2、基类与派生类对象的赋值转换(切片)
a、派生类对象可以赋值给基类的对象/基类的指针/基类的引用。(把派生类中父类那部分切来赋值过去)
b、基类对象不能赋值给派生类对象
class Person
{
protected:
string _name;
string _sex;
int _age;
};
class Student: public Person
{
public:
int _No;
};
void Test()
{
Student s;
//子类对象可以赋值给父类对象/指针/引用
Person p = s;
Person* pp = &s;
Person& rp = s;
}
3、继承中的作用域、隐藏
a、在继承体系中基类和派生类都有独立的作用域
b、子类和父类中有同名的成员,子类成员将屏蔽父类对同名成员的访问,这种情况叫隐藏,也叫重定义(在子类成员函数中,可以使用基类::基类成员 显示访问)
//B中的fun和A中的fun不构成重载,因为不在同一作用域中
//B中的fun和A中的fun构成隐藏
class A
{
public:
void fun()
{
cout << "fun()" << endl;
}
};
class B : public A
{
public:
void fun(int i)
{
A::fun();
cout << "func(int i)->" << i << endl;
}
};
4、派生类的默认成员函数、
有6个默认成员函数完成以下功能:
初始化和清理:构造函数、析构函数
拷贝复制:拷贝构造函数、赋值重载
取地址重载:普通对象和const对象取地址,这两个很少自己实现
class Person{public :Person ( const char* name = "peter" ): _name ( name ){cout << "Person()" << endl ;}Person ( const Person & p ): _name ( p . _name ){cout << "Person(const Person& p)" << endl ;}Person & operator = ( const Person & p ){cout << "Person operator=(const Person& p)" << endl ;if ( this != & p )_name = p . _name ;return * this ;}~Person (){cout << "~Person()" << endl ;}protected :string _name ; // 姓名};class Student : public Person{public :Student ( const char* name , int num ): Person ( name ), _num ( num ){cout << "Student()" << endl ;}Student ( const Student & s ): Person ( s ), _num ( s . _num ){cout << "Student(const Student& s)" << endl ;}Student & operator = ( const Student & s ){cout << "Student& operator= (const Student& s)" << endl ;if ( this != & s ){Person::operator = ( s );_num = s . _num ;}return * this ;}~Student (){cout << "~Student()" << endl ;}protected :int _num ; // 学号};void Test (){Student s1 ( "jack" , 18 );Student s2 ( s1 );Student s3 ( "rose" , 17 );s1 = s3 ;}
5、继承与友元、继承与静态成员
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员
class Student ;class Person{public :friend void Display ( const Person & p , const Student & s );protected :string _name ; // 姓名};class Student : public Person{protected :int _stuNum ; // 学号};void Display ( const Person & p , const Student & s ){cout << p . _name << endl ;cout << s . _stuNum << endl ;}void main (){Person p ;Student s ;Display ( p , s );}
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 TestPerson (){Student s1 ;Student s2 ;Student s3 ;Graduate s4 ;cout << " 人数 :" << Person :: _count << endl ;Student :: _count = 0 ;cout << " 人数 :" << Person :: _count << endl ;}
6、多继承
多继承:一个子类有两个或以上的父类
菱形继承:菱形继承是多继承的一种特殊情况
菱形继承的问题:从下面的成员模型构造,可以看出菱形继承有数据冗余和二义性问题,在Assistant的对象中Person成员会有两份。虚拟继承可以解决这个问题,虚函数就留到下一个知识点多态总结。