类的兼容性原则

父类指针可以new子类对象,子类指针不可以new父类对象,但是可以接收强转的已经存在的父类指针 父类指针指向本类对象,调用的虚函数和普通函数都是自己的 将子类指针指向父类对象,虚函数执行的是父类的,也可以调用子类函数(这种操作是错误的,编译会报错,虽然可通过指针强转,但是不建议这样做,可能会导致未知错误) 父类指针指向子类对象,虚函数执行的是子类的,并且不能调用子类的函数 父类指针与子类指针之间赋值可以理解为指针所指内容的一种浅拷贝 Father *f = (Father*)Child * 子类的虚函数指针覆盖父类的,并且子类特有的函数指针不会拷贝过去 Child *c = (Child*)new Father父类的虚函数指针覆盖子类的,同时也有子类特有的函数指针 class A{ public: void printA(){ cout << "printA()" << endl; } virtual void print(){ cout << "A::print()" << endl; } }; class B:public A{ public: void printB(){ cout << "printB()" << endl; } virtual void print() override{ cout << "B::print() b = " << b << endl; } private: int b; }; int main( ) { // 1、指向自己的类对象(将父类对象赋值给父类指针) A *a = new A; // 1....

December 28, 2021 · 1 min · Rick Cui

构造函数私有

如果类的内部没有专门创建实例的代码,则是无法创建任何实例的 如果父类构造函数设置成了私有的,则子类无法编译,因为在初始化子类时会先执行父类的构造 class A{ public: private: A(int ){ } }; class B:public A{ public: int x; }; int main( ) { B b; b.x = 0; return 0; } 输出: Start prog.cc:19:7: error: call to implicitly-deleted default constructor of 'B' B b; ^ prog.cc:13:9: note: default constructor of 'B' is implicitly deleted because base class 'A' has an inaccessible default constructor class B:public A{ ^ 1 error generated. 1 Finish

December 28, 2021 · 1 min · Rick Cui

定义一个只能在堆上(栈上)生成对象的类

一、只能在堆上 方法:将析构函数设置为私有 原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象 class Test { public: void printT(){ cout << "printT" << endl; } void freeT(){ delete this; } private: ~Test(){ cout << "~Test()" << endl; } }; int main( ) { // 不能在栈上创建对象 //Test t; // prog.cc:25:10: error: variable of type 'Test' has private destructor // 只能在堆上创建对象 Test *t = new Test; t->printT(); // 销毁对象 t->freeT(); return 0; } 输出: Start printT ~Test() 0 Finish 二、只能在栈上 方法:将 new 和 delete 重载为私有...

December 27, 2021 · 1 min · Rick Cui

抽象类、接口类、聚合类

抽象类:含有纯虚函数的类,不能实例化对象 接口类:仅含有纯虚函数的抽象类 聚合类:用户可以直接访问其成员,并且具有特殊的初始化语法形式。满足如下特点: 1)所有成员都是 public,没有私有和受保护的非静态成员; 2)没有定义任何构造函数; 3)没有类内初始化; 4)没有基类,也没有 virtual 函数 // 接口类 class A { virtual void printA() = 0; // 纯虚函数 }; // 抽象类 class AA:public A { public: // 覆写接口类的纯虚函数 void printA() override { cout << "class AA printA()" << endl; } virtual void printAA() = 0; }; // 可实例化的类 class B:public AA { public: // 覆写父类(抽象类)的纯虚函数 void printAA() override { cout << "class B printAA()" << endl; } void printB() { cout << "printB()" << endl; } }; // 聚合类 class C { public: int x; int y; void print(){ cc(); } private: void cc(){ cout << "x = " << x << ", y = " << y << ", z = " << z << endl; } static int z; }; int C::z = 0; class D { public: int a; int b; C c; void print(){ cout << "a = " << a << ", b = " << b << endl; c....

December 27, 2021 · 1 min · Rick Cui

虚继承和虚基类

虚继承和虚基类 参考 在C++中,在定义公共基类A的派生类B、C…的时候,如果在继承方式前使用关键字virtual对继承方式限定,这样的继承方式就是虚拟继承,公共基类A成为虚基类。这样,在具有公共基类的、使用了虚拟继承方式的多个派生类B、C…的公共派生类D中,该基类A的成员就只有一份拷贝 一个类有多个基类,这样的继承关系称为多继承。在多继承的情况下,如果不同基类的成员名称相同,匹配度相同, 则会造成二义性。为了避免多继承产生的二义性,在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含一份虚基类的成员。 会在虚继承的类中生成一个指向虚基类的指针 {vbptr} 会在内存中生成一个虚基类表 D::$vbtable@B@ 微软的Visual Studio提供给用户显示C++对象在内存中的布局的选项 cl [filename].cpp /d1 reportSingleClassLayout[className] 一般继承: class A { public: int dataA; }; class B:public A { public: int dataB; }; class C:public A { public: int dataC; }; class D : public B, public C { public: int dataD; }; 输出: class D size(20): +--- 0 | +--- (base class B) 0 | | +--- (base class A) 0 | | | dataA | | +--- 4 | | dataB | +--- 8 | +--- (base class C) 8 | | +--- (base class A) 8 | | | dataA | | +--- 12 | | dataC | +--- 16 | dataD +--- 调用:...

December 27, 2021 · 2 min · Rick Cui