多态
C++的封装、继承和多态三大特性,封装没什么好说的,就是把事务属性和操作抽象成为类,在用类去实例化对象,从而对象可以使用操作/管理使用它的属性。
至于继承,和多态密不可分。基类可以进行派生,而派生类则是继承基类或称父类,把基类中属性和方法拿过来,变成自己的一部分,其中需要较为精细的思考。
多态则是一种实现多种使用的手法,这样的说法不太准确。静态多态(编译时多态)我觉得是函数重载,不再赘述了,要注意的是重载函数的二义性(PS.Tencent interview TEG)。动态多态/运行时多态,又称动态绑定。动态绑定的基础是虚函数和使用基类指针或引用调用基类函数,只要用virtual声明了虚函数,那么它的调用对象就要运行时才能确定。它的实现机制在《深度探索对象模型》中有较为晦涩的解释。
基类指针或是引用调用虚函数会发生运行时绑定,但是非虚函数则不会,还是编译时绑定,它的动态类型和静态类型是一致的。
纯虚与抽象
虚函数声明尾连接 “= 0” 是的该该虚函数成为纯虚函数,作为接口,供派生类覆盖实现。
含有纯虚函数的类是抽象类,不能进行实例化,只能作为基类供子类继承以实现声明的纯虚函数。
(实例化抽象类的错误信息)
一个例子
1 #include <iostream> 2 using namespace std; 3 4 //抽象基类 5 class abstract 6 { 7 protected: 8 int m; 9 public: 10 string name; 11 public: 12 abstract() = default; 13 ~abstract() = default; 14 virtual void set(string _name) = 0; 15 virtual string get() const = 0; 16 }; 17 18 //派生类 19 class Son : public abstract 20 { 21 private: 22 int count; 23 public: 24 Son() = default; 25 ~Son() = default; 26 void set(string _name) override; 27 string get() const override; 28 }; 29 30 void Son::set(string _name) 31 { 32 this->name = _name; 33 this->count = 20; 34 this->m = 20; 35 } 36 37 string Son::get() const 38 { 39 return this->name + to_string(this->m); 40 } 41 42 int main() 43 { 44 Son s; 45 s.set("yoci"); 46 cout << s.get() << endl; 47 48 return 0; 49 }
访问控制
private:仅类内可见,其他不可见;
protected : 类内可见,派生类可见;
public:都可访问。
基类虚析构
一般我们把基类的析构函数设置成为虚函数,且采用默认实现的版本。
是为了避免,使用动态绑定时,基类指针指向派生类对象并进行析构时,采用(静态类型)基类析构函数而出现错误的情况。