c++中类有三大特性:封装性 继承性和多态性
继承目的:在C++中,继承最主要的目的是提供代码的可重用性
继承:如何判断类与类之间存在着继承呢?可通过类与类之间的关系:is-a
如果两个类存在is-a的关系,那么,它们就可以使用继承
has -- a 是一种包含和组合的关系,比如:电脑包含CPU,主板,硬盘
1 继承与组合及继承方式
语法:
父类(基类)
子类(派生类)
class 派生类:[继承方式] 基类名
{
派生类
}
继承方式:private(默认继承方式) --- 私有继承
public---公有继承
protected --- 保护继承
继承方式跟类成员访问修饰符关键字是一样,但是他们的意义不一样
一个是派生类从基类所继承的方式
另一个是类中成员对外部和内部的访问权限
对于访问权限修饰符,在一个类中,private和protectd修饰的类成员,完全一
样,而在继承中他们有所不同
继承的分类:
单继承 :派生类只有一个基类
多继承:派生类可以同时有多个基类
派生类与基类成员关系:派生类对基类成员是全盘接收,除了构造函数和析构函数
派生类内存分配空间:
继承方式所得出的结论:
public protected private -----> 基类中成员所对应的访问权限修饰符
公有继承(public) public protected 不可见 -----> 基类中的成员通过继承在派生类所体现的成员访问权限
保护继承(protectd)protected protected 不可见
私有继承(private) private private 不可见
2 继承中的构造和析构
情况一: 派生类没有其他类类型
派生类的构造:先调用基类的构造函数,再调用派生类构造函数
派生类的析构:先调用派生类的析构函数,再调用基类的析构函数
情况二:派生类中有类类型
//派生类的构造:
//若派生类有内嵌类型声明,基类构造 ----> 内嵌子对象构造函数(如果有多个内嵌对象,调用顺序跟声明顺序有关) ---> 派生类构造
//析构顺序:派生类 ---- 内嵌子对象 --- 基类,与构造的顺序相反
//为了解决基类的成员初始化问题,在派生类引入构造函数初始化列表来进行
Derived(int t =0,int b = 2,const Test& t1 = 0):Base(b),d(t),t1(t1)
{
cout << "Derived(int t =0,const Test& t1 = 0)" << endl;
// this->setB(b); //不建议
// this->Base(b); error 构造函数不会被派生继承
}
一 Shadow现象-----继承中同名变量和成员函数
Shadow现象,不是必须会发生,Shadow时机,会发生在基类和派生类中出现重名成员 (包括成员变量和成员函数),此时,派生类会shadow所有父类中的重名成员。 若要使用父类的重名成员,必须通过 类名::来限定重名成员的作用域。
//Shadow(影子 隐藏)
class A
{
public:
void printT()
{
cout << " A::printT()" << endl;
}
};
class B:public A
{
public:
void printT()
{
cout << " B::printT()" << endl;
//本意是调用父类的接口printT()
//printT(); //相当于this->printT();
A::printT(); //A:: 不是指调用,而且限定函数的作用域
}
};
int main()
{
B b;
//在调用时候,不会出现朝二义性,会调用子类中的函数
b.printT();
A a = b; //使用子类对象来初始化父亲的对象
a.printT(); //调用的是A类(基类)还是B类(派生)中 // 调用基类中成员函数
A& aa = b; //
A* pa = &b;
return 0;
}
二 多继承
一个派生类可以有多个基类
语法:
class 派生类:继承方式 基类1, 继承方式 基类2
{
}
比如:
class SafaBed:public Safa,public Bed
{
}
在多继承中,多个基类中重名的成员,继承到派生类中,为了避免冲突,携带了各基类的 作用域信息,派生类要访问继承下来的和重名成员,访问时需要提供基类的作用域限定信息
class SaFa
{
public:
int m; //材质
};
class Bed
{
public:
int m; //材质
};
class SaFaBed:public Bed,public SaFa
{
//对于派生类中,从不同的基类中,继承得到相同名字成员 --- 三角问题
//1.数据冗余
//2.重名成员,使用起来不方便
//为了解决三解,在C++中,有了更好解决方案:将三角转四角(菱形)
/*
1,提取公因式,提取各基类中相同的成员,构成祖父类(虚基类)
2.让各基类,继承祖父类,继承的方式,采用虚继承
3.虚继承是继承的一种扩展
*/
public:
void printSB()
{
//main.cpp:25:11: error: member 'm' found in multiple base classes of different types
// main.cpp:15:9: note: member found by ambiguous name lookup
// main.cpp:8:9: note: member found by ambiguous name lookup
SaFa::m = 10;
Bed::m = 30;
sb = 20;
cout << SaFa::m <<" ---" << Bed::m << " ----" << endl;
}
int sb;
};
int main()
{
SaFaBed s;
s.printSB();
return 0;
}