1 为什么要用继承?
继承是代码的复用的一种实现,呈现了oop的层次结构,继承是类设计层次的复用。
2 继承的风格
class A{};
class B :public A{};
:为继承符号
A为被继承类称为 基类
B为继承类 ,称为派生类
public称为继承方式 :
继承方式分为 public protected private 三种
同样 访问限定符也分为 public protected private 三种
3 继承基类成员访问方式的变化 :
1 基类为 private时 ,派生类不可见
2 基类非private时,访问方式选继承方式和访问方式中最高
(不可见的意思,已经继承下来了,但是无法访问)
访问限定符等级 public < protected < private
即 private等级最森严
3使用关键字 class 时默认的 继承方式是 private ;使用struct默认关键字为 public, 最好显示表明继承方式。
4 实际大多用 public 作为继承方式, 几乎很少使用 private / protected作为继承方式,because , 用了他俩就只能在派生类中使用,导致扩展维护性不强。
5 派生类对象可以给基类的对象 / 基类的引用 /基类的指针 赋值,但反过来不行。
6 基类的指针要给派生类指针赋值时,需要在基类指针指向派生类对象的前提下 ,再进行强制类型转换,否则不安全哦!
4 继承的作用域
派生类中若出现和基类同名的成员时,则会将基类屏蔽掉,优先使用派生类的成员。
要使用基类的成员,需要 基类 ::成员
5 继承与友元
一句话 ,友元关系在继承时不传递
#include "iostream"
#include"string"
//#include"windows.h"
using namespace std;
class Student;
class Person
{
friend void Display(const Person& p, const Student& s);
protected :
string _name="小李子";//C++11新玩法的默认值
};
class Student : public Person
{
protected:
string _stuNum;
};
void Display(const Person& p, const Student& s)
{
cout << p._name << endl;
//cout << s.stuNum << endl;//注意这个不可访问 ,因为友元关系继承后在派生类中失效
}
int main()
{
Person p;
Student s;
Display(p, s);
system("pause");
return 0;
}
6 继承与静态成员
一句话 静态成员只存在一份,不管在哪修改或查看效果一样
#include"iostream"
#include"string"
using namespace std;
class Person
{
public :
Person() { ++_count; }
private :
string _name;
public :
static int _count;
//public :
// void print()
// {
// cout << _count << endl;
// }
};
int Person:: _count = 0;
class Student :public Person
{
protected :
string _stuNum;
};
class Graduate//研究生
{
protected:
string _seminarCourse;//研究课程
};
int main()
{
Person s;
Student a;
Student b;g
Student c;
Student d;
Graduate g;
//s.print();
cout << Person::_count << endl;
Student::_count = 0;
cout << Person::_count << endl;//我们发现 static 只存在一份,而且是同步变化的
system("pause");
return 0;
}
7复杂的继承与菱形继承
图片一目了然 ,不多介绍了 ,
菱形继承 存在的问题:数据冗余和二义性,我们采用*虚拟继承来解决
#include"iostream"
#include"string"
using namespace std;
class Person
{
public:
string _name;
};
class Student :virtual public Person
{
public :
void Change()
{
this->_name = " Peter";
cout << this->_name << endl;
}
protected:
int _stuNum;//学号
};
class Teacher : virtual public Person
{
public:
void A() { cout << "hello" << endl; }
protected:
int _num;//职工号
};
class Assistant :public Student,public Teacher
{
protected:
string _course;//主修课程
};
int main ()
{
Assistant a;
cout << "A :" << a._name << endl;
Student s;
/*Person p;
s.Change();*/
Teacher t;
//cout << "T :" << t._name << endl;//我们发现 使用虚拟继承后 两个类没啥关系了
s._name = "S";
cout << "S :"<<s._name << endl;
a._name = "peter";
a.A();
cout << "A :" << a._name << endl;
cout << "T :" << t._name << endl;//我们发现 使用虚拟继承后 本类并不会修改两个父类,但却能调用两个父类的成员
cout << "S :" << s._name << endl;
system("pause");
return 0;
}
我们发现:虚拟继承可以解决菱形继承的数据冗余和二义性问题;
但需要注意的是 ,虚拟继承不要用在别的地方。
虚拟继承解决数据冗余和二义性的原理:
#include"iostream"
#include"windows.h"
using namespace std;
class A {
public :
int a;
};
class B : virtual public A
{
public:
int b;
};
class C : virtual public A
{
public:
int c;
};
class D : public B, public C
{
public:
int d;
};
int main()
{
D d;
d.A::a = 1;//这个时候存在两份a , d中一份 A中一份,互不相同,但d两个a都可以访问
d.B::b = 2;//b跟a的原理相同
d.b = 3;
d.c = 4;
system("pause");
return 0;
}
怎么禁止一个类被继承?
C++98 将构造函数私有化 ,
C++11 使用final ,直接放在 类名后边关键字
总结
:一般不建议设计出多继承,一定不要设计出菱形继承,否则性能和复杂度上都存在问题。
能使用组合,也能使用继承,优先使用组合