//多态的语法本质分析 #include<iostream> using namespace std; /* 三种易混淆的多态场景 */ class Point{ public: Point(int b=0){ this->b = b; } virtual void Print(){ cout << "父类的虚函数" << endl; } private: int b; }; class PointA :public Point{ public: virtual void Print(){ cout << "子类重写父类的虚函数" << endl; } }; void ProtectB(){ PointA pa ; //场景① Point p1; p1 = pa; p1.Print(); //执行p1 = pa;完成的是将子类对象中父类部分的数据拷贝到父类对象中(我并不是说子类对象中有父类对象,子类对象就是子类对象,没有父类对象) //这个操作并没有使父类对象在内存里变成子类对象,没有分配新的内存,p1对象所占的内存空间还是那么大,只是简单的数据拷贝 //p1.Print();他的真身是父类对象调用自己的虚函数,那么执行的还是自己的虚函数 //场景② Point p2 = pa; p2.Print(); //p2不会产生多态,因为Point p2 = pa;本质上是调用了p2的默认拷贝构造函数 //用子类对象初始化父类对象,本质上还是将子类对象中父类部分的数据拷贝到父类对象中 //p2在内存中的大小仍然是sizeof(Point) //p2.Print();他的真身是父类对象调用自己的虚函数,那么执行的还是自己的虚函数 //场景③ //但是下面的例子是完全不同的 PointA *pa2 = new PointA(); Point *p3 = NULL; p3 = pa2; //这里的p3 = pa2;和上面试完全的不同 pa2是一个指针,指向一个子类对象的内存空间 //通过 p3 = pa2; 使得父类指针p3指向了子类对象的内存空间 p3->Print(); //此时p3->Print();会发生多态 /* 由此得出结论:多态的语法本质是:父类指针指向了一个子类对象(c++引用本质上是一个常量指针) 而且我认为在多态的场景中使用父类指针加法运算是危险的 父类的步长是sizeof(Point)个大小的字节,子类的步长是sizeof(PointA),这两个对象的步长未必相同,因为子类可能添加了自己的私有属性 例如p3++;非常危险 */ delete pa2; } void main(){ ProtectB(); system("pause"); }