继承
因为本科的时候接触过一段时间java,对继承这个概念印象深刻。
继承限定词
public:父类怎样子类就怎样
class CChild: public CPeaple
{
};
protected:继承之后,父类的public降级成protected,父类中的protected和private不变
父类中的属性不会改变
class CChild: protected CPeaple
{
};
private:继承之后,父类中都降级成private
class CChild: private CPeaple
{
};
成员的继承
无参构造函数:
继承构造的调用顺序:先父类再子类;
含参构造函数
如果父类有构造函数,且有参数,子类的构造函数一定要写出来。参数在参数列表传递
class CFather
{
public:
CFather(int a);
{
}
}
class CSon:public CFather
{
public:
int a;
CSon():CFather(1);
{
}
};
参数传递只能两级之间。如果CFather继承了别的类,只需在CFather类中加入参数列表,和CSon没关系。
当有多个构造函数时,根据参数列表的个数决定调用哪个构造函数
析构函数
析构函数调用顺序:先子类再父类
覆盖
在子类中有和父类中同名的数据成员,把父类中的覆盖,如果想在子类中用父类的数据成员:
类内:
cout<<CFather::a<<end;
类外:
CSon so;
cout<<so.CFather::a<<endl;
子类函数和父类函数同名,并不是重载,调用的时候必须使用CFather::来调用父类的函数。
友元函数不能被继承
多态和虚函数
多态只针对指针对象,虚函数只针对于函数成员;
父类的指针调用子类的函数
CFather *fa = new CSon;
fa->show()//普通函数只能调用父类自己的成员
虚函数virtual:
//父类:
virtual void show()//虚函数
{
cout<<"father"<<endl
}
//子类:
void show()
{
cout<<"son"<<endl
}
//main:
CFather *fa = new CSon;
fa->show()//用父类的指针调用子类的成员
只有函数名字一样,才能达到这个虚函数调用效果。
重写
针对虚函数;
1.父类是虚函数,子类重写的函数,默认是虚函数;
返回值类型必须相同
2.特殊情况(协变):
当返回的是当前类的引用或者指针,返回值的类型可以是各自类类型。
3.虚函数不能是内联函数
4.构造函数不能是虚函数
虚表
CFather* fa=new CSon;
fa->show;
*(int*)fa//获得的是虚表的首地址
把对象的首地址转成int (四字节) ,然后取对象首地址的地址
*(int*)*(int*)fa//获得的是虚表的第一个的地址内容(fun)
*((int*)*(int*)fa+1)//获得的是续表第二个的地址内容(show)
虚表的首地址并不知道是什么类型,所以要先转换成int*,然后递增
代码实现:
typedef void (*p)();
((p)(*(int*)*(int*)fa+0)))()//调用 取内容 fun
虚析构
多态中,如果释放父类指针,只会调用父类的析构函数,变成虚析构后,子类父类都调用