抽象类、接口类、聚合类

抽象类:含有纯虚函数的类,不能实例化对象 接口类:仅含有纯虚函数的抽象类 聚合类:用户可以直接访问其成员,并且具有特殊的初始化语法形式。满足如下特点: 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

多态总结

1. C++ 多态分类及实现 重载多态(Ad-hoc Polymorphism,编译期):函数重载、运算符重载(静态多态、静态编译) 子类多态(Subtype Polymorphism,运行期):虚函数(动态多态、动态编译) 参数多态(Parametric Polymorphism,编译期):类模板(泛型)、函数模板(函数指针) 强制多态(Coercion Polymorphism,编译期/运行期):基本类型转换、自定义类型转换 2. 虚表指针、虚函数指针、虚函数表 虚表指针:在含有虚函数的类的对象中,指向虚函数表的指针,在运行时确定 虚函数指针:指向虚函数的地址的指针 {vfptr} 虚函数表:在程序只读数据段,存放虚函数指针,如果派生类实现了基类的某个虚函数,则在虚函数表中覆盖原本基类的那个虚函数指针,在编译时根据类的声明创建 Shape::$vftable@ class Shape { public: virtual ~Shape(){ cout << "~Shape()" << endl; } }; class Point { public: ~Point(){ cout << "~Point()" << endl; } private: int m_x{0}; int m_y{0}; char m_c; }; class Circle : public Shape { public: ~Circle(){ cout << "~Circle()" << endl; } private: Point m_p; }; int main( ) { // 8 类中存有指向虚函数表的指针 cout << sizeof(Shape) << endl; // 16 类中存有指向虚函数表的指针 // 以及Point对象的大小(此时Point类中不包含任何变量),虽然真实大小是 8 + 1 // 但是额外多的1个字节导致内存大小扩增了 8(每次扩增的最小数值是8 <alignment member> (size=7)) cout << sizeof(Circle) << endl; // 8 类中的int占4个字节,char占1个字节 // 但每次扩增的最小数值是4(<alignment member> (size=3)) cout << sizeof(Point) << endl; Circle c; return 0; } Start 8 24 12 ~Circle() ~Point() ~Shape() 0 Finish Shape 类...

December 27, 2021 · 2 min · Rick Cui

函数默认参数和占位参数

1. 函数默认参数和占位参数(亚元) 形参中的占位参数又叫亚元,并没有什么实际意义,只在函数重载中起到作用 // 亚元,设置了默认值所以调用时可以不传参数 // 否则就必须传入两个参数 void foo(int a, int = 0){ cout << "a = " << a << endl; } int main() { foo(20); return 0; } 2. 函数重载 函数名相同,形参列表不同(形参个数、类型、顺序) 函数返回值不起作用 函数重载和默认参数不要同时使用(函数调用时容易产生二义性) 倾轧技术(name mangling),底层会将函数名进行编译 用 v c i f l d 表示 void char int float long double 及其引用 int fun(int) => fun_i int fun(int, char, double) => fun_icd 重载函数匹配顺序 如果能够严格匹配,则调用完全匹配的 如果没有完全匹配的,则调用隐式转换的 都匹配不上,编译失败 3....

December 26, 2021 · 1 min · Rick Cui

内存区间划分

一、程序运行前 代码区(只读的、共享) 数据区(全局变量和静态变量) 二、程序运行后 栈区 堆区 全局静态区(全局变量、静态变量、常量) 代码区 Linux程序运行内存虚拟地址空间: 三、全局变量与静态变量的区别 作用域不同 全局变量默认是 extern 的 静态变量是文件作用域 C/C++ 中 extern 关键字详解

December 26, 2021 · 1 min · Rick Cui