派生类访问权限
派生类对象的体积 = 基类对象的体积 +派生类对象自己的成员变量的体积 ,派生类对象包含着基类对象,积累对象存储的位置位于派生类对象新增的成员变量之前
C++类和结构体中缺省的为私有成员
类的成员函数以外的地方,只能访问该类对象的公有成员
通过public成员函数,可以通过参数访问类的私有成员变量
class cDog;
Class cMaster {
cDog dogs[10];
}
Class cDog{
cMaster m;
}
//循环定义计算不出体积大小,为了避免循环定义,为“业主”类设置一个“狗”类的对象指针数组
class cMaster{
cDog *dogs[10];//10个元素的指针数组,每个元素都是一个指针,字节数就是40个字节
}
基类和派生类有同名函数的情况下
base::i = 5;//访问基类的成员变量
base::func();//基类的成员函数
基类的private成员可以被
1.积累的成员函数访问
2.基类的友元函数访问
派生类的成员函数可以访问当前类对象的基类的保护成员
class Father{
protected:
int nProtected;
}
class Son:public Father{
void AccessFather(){
nProtected =1;//ok,访问从基类继承的Protected成员
Son s;
s.nProtected =1; //wrong,s不是AccessFather所属的对象,不是当前继承基类的对象
}
}
Base(int i):n(i){} //构造函数就是用i初始化n的值
执行派生类的构造函数之前:调用基类的构造函数
1、初始化派生类从基类继承的成员
2,调用成员对象类的构造函数
3,初始化派生类对象的成员
public继承的赋值兼容原则
class base{};
class derived:public base{};
base b; derived d;
1.派生类对象可以赋值为基类对象
b =d ;
2.派生类对象可以初始化为基类的引用
base &br = d;
3.派生类对象的地址可以赋值给基类的指针
base *pb = &d;
如果派生方式是private,protected,以上3条不行
虚函数
virtual关键字只用在类定义的函数声明中,写函数体时不用
构造函数和静态成员函数不能是虚函数
虚函数和普通函数的本质差别是:虚函数参与多态,普通函数不能
Class 派生类名 :继承方式1(访问权限) 基类名1 ,继承方式2(访问权限) 基类名2
多态:在运行的过程中根据函数的参数类型,确定调用哪一个函数
virtual 使speak成为虚函数,实现基类指针访问派生类成员函数
virtual的用途是:实现运行时的多态性,通过基类指针访问派生类同名覆盖函数
应通过指针或引用调用虚函数,而不是以对象名来调用虚函数
在派生类中重新定义基类的虚函数仍为虚函数,同时可以省略virtual关键字
将不用来声明(实例化)对象的类称为抽象类,只供继承
抽象类又可以定义成:至少包含一个纯虚函数的类
面向对象:采用对象来描述内部属性和操作方法,将数据和函数当做一个整体
继承:在...的基础上,又有什么样的新特征
destructor往往用于释放constructor中动态申请的内存空间
所有对象中的成员函数共用一个存储空间,在代码区存放
class base{
virtual int get();
}
int base::get(){};
纯虚函数的定义:
纯虚函数:一点都不务实全虚的,没有函数体的虚函数在当前类什么都做不了
virtual 返回类型 函数名(参数表) = 0,具体实现只能在派生类中完成
virtual double Area() = 0;
连函数体都没有的虚函数就是纯虚函数,这类对象一般是抽象的概念,比如shape类,没有面积不需要打印信息
虚函数是应在派生类中重新定义的成员函数。 当使用指针或对基类的引用来引用派生的类对象时,可以为该对象调用虚函数并执行该函数的派生类版本。
在构造和析构函数中调用虚函数不是多态,初始化时子类先调用基类的构造函数,此时,子类还未被初始化不能是多态
抽象类:包含纯虚函数的类
1.不能创建对象
2.只能作为基类派生新类使用
3.抽象类的指针和引用指向派生出的新类的对象
如果从一个抽象类派生而来,它实现了基类中 所有加{}的纯虚函数,才能身份转变成为非抽象类
Class Base{
public:
int i;
virtual void print(){
cout<<"Base Print"<<endl;
}
}
sizeof(Base) =8;//不是4,猜猜为什么?
每一个有虚函数的类都有一个虚函数表,该类的对象放着虚函数表的指针,虚函数表中列出了该类的虚函数地址,多出的4个字节就是用来存放虚函数地址的,通过虚函数表可以查询函数在内存中的地址,调用函数就是跳到内存地址上去执行
int main(){
CSon *p =new CGrandson;
delete p;//指针指向CSon,只会调用CSon的析构函数,派生类无法被调用内存不释放,怎么解决呢?
}
把基类的析构函数声明为virtual,派生类析构函数可以不声明,通过积累的指针删除派生类对象时,先调用派生类的析构函数,再调用基类的析构函数,类如果定义了虚函数,最好将析构函数定义成虚函数,不允许虚函数作为构造函数
构造函数:名字和类名相同,可以有参数,不能有返回值
对象占用的存储空间是不是构造函数分配的?
构造函数是在对象已经占用的存储空间做一些初始化的工作,如果把对象比作房子,构造函数不是盖房子只是进行装修