C++ 类的多态五(多态的语法本质分析)

//多态的语法本质分析
#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");
}
原文地址:https://www.cnblogs.com/zhanggaofeng/p/5639563.html