c++——类 虚函数 虚基类 多态 this指针的深解
//虚基类 //类中如果出现virtual关键字,类对象的大小多四字节,出现在继承上面叫虚继承 //如果继承链中有虚基类,优先构造虚基类 //如果虚基类需要带参构造,不管是直接继承还是间接继承都需要给虚基类传参 //关键字virtual必须位于类名前,只对一个类名起作用 class CB : public virtual CA class CB : virtual public CA void virtual run(); virtual void run(); //都对
//多态 //C++中的多态性具体体现在运行和编译两个方面。 //运行时多态是动态多态,其具体引用的对象在运行时才能确定。 //编译时多态是静态多态,在编译时就可以确定对象使用的形式。 //同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。 //在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。 //函数的重载不认为是多态,多态只会发生在继承关系里面 一个指令对应多种行为
//类中有数据是按数据类型计算大小,,若没有,有函数,一共占一个字节; class CM { public: void abc(){ printf("CM-abc"); } void def(){ printf("CM-def"); } }; void main() { CM m; printf("大小%d\n", sizeof(CM)); // 1 字节, 虽然说一共有两个函数 } //--------------------------------------------------------- class CM { int a; public: void abc(){ printf("CM-abc"); } void def(){ printf("CM-def"); } }; void main() { CM m; printf("大小%d\n", sizeof(CM)); // 4 字节 } //--------------------------------------------------------- class CM { public: void virtual abc(){ printf("CM-abc"); } void virtual def(){ printf("CM-def"); } }; void main() { CM m; printf("大小%d\n", sizeof(CM)); // 4 字节 加了virtual虚函数 虚基类 4字节 } //--------------------------------------------------------- class CM { int a, b; public: CM(){ a = 10; b = 20; } int getA(){ return a; } void virtual abc(){ printf("CM-abc %d\n", a); } void virtual def(){ printf("CM-def %d\n", b); } }; typedef void(*pFun)(); int main() { pFun pf; CM m; printf("打印a %d\n", m.getA()); //a = 10; for (int i = 0; i < 2; ++i) { pf = (pFun)*((int *)*(int *)(&m) + i); pf(); //a,b都没有初始化 } printf("大小%d\n", sizeof(CM)); // 12 字节 加了virtual虚函数 虚基类 4字节 return 0; }
//类中出现了虚函数关键字,会多出4字节莫虚函数列表(函数指针数组首地址) //虚函数列表中放什么东西,类中的虚函数的首地址全部放进去 //如果发生继承关系:1.基类和派生类各有各的虚函数列表(虚函数数组不继承) // 2.虚函数数组元素继承 // 3.如果派生类给出同名元素后会发生覆盖
//虚函数:类中有虚函数,析构写成虚析构 //虚析构可以在函数 class CA { public: CA(){ printf("CA\n"); } virtual ~CA(){ printf("~CA\n"); } void virtual run(){ printf("CA::RUN()\n"); } }; class CB : public CA { public: CB(){ printf("CB\n"); } ~CB(){ printf("~CB\n"); } void virtual run(){ printf("CB::RUN()\n"); } }; void main() { CB b; CA* pa; //没有调用构造函数 pa = &b; pa->run();//CB 构造顺序 CA CB CB::RUN ~CB ~CA //另一种 CA *pa = new CB(); pa->run(); delete pa; //构造顺序 CA CB CB::RUN ~CA }
靠技术实力称霸,千面鬼手大人万岁!