多態體驗,和探索爺爺類指針的多態性

 

1. 多態初體驗

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:

    virtual void print()
    {
        cout << "I'm Parent." << endl;
    }
};

class Child : public Parent
{
public:

    void print()
    {
        cout << "I'm Child." << endl;
    }
};

void how_to_print(Parent* p)
{
    p->print();
}

int main()
{
    Parent p;
    Parent*pfather = &p;

    Child c;
    Parent* pson =  reinterpret_cast<Parent*>(&c);
    Parent* p = pson;  // p也具備多態性 

    how_to_print(pfather);
    how_to_print(pson);
    how_to_print(p);

    pson_2 = pfather;
    how_to_print(p);

    return 0;
}

現象:p具備多態性
小結: 指向子類對象的父類指針被傳遞後,依然具備多態性。

 

2.  探索爺爺類的多態

實驗一:

爺爺類(父類的父類)是抽象類,看能否在孫類(子類的子類)身上,實現一個方法(成員函數)的多態調用。

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    virtual void print() = 0;
};

#if 0 // 方式1
class Child : public Parent
{
public:

    virtual void print() = 0;

};
#else // 方式2
class Child : public Parent
{
public:
    void print() {
        cout << "Child: print()" << endl;
    }

};
#endif

class GrandSon : public Child
{
    string name;
public:
    GrandSon(char* n_name)
    {
        name = string(n_name);
    }

    void print()
    {
        cout <<  "GrandSon::print() :" << name << endl;
    }
};

void how_to_print(Parent* p)
{
    p->print();
}

int main()
{
    GrandSon gson1("jason");
    how_to_print(reinterpret_cast<Parent*>(&gson1));
    Parent* pgson1 = reinterpret_cast<Parent*>(&gson1);

    cout << endl;
 
    GrandSon gson2("polly");
    Parent* pgson2 = reinterpret_cast<Parent*>(&gson2);
    how_to_print(pgson2);

    cout << endl;
    // 下面是拓展實驗
    Parent* gson_current = pgson1;
    how_to_print(gson_current);

    return 0;
}

小結: 爺爺類(父類的父類)是抽象類時,中間層的父類是抽象類也罷,或者實現了自己的多態方法也罷,此時, 當爺爺類指針指向孫類對象,依然具備多態特性。

 

實驗二:

爺爺類(父類的父類)是非抽象類,看能否在孫類(子類的子類)身上,實現一個方法(成員函數)的多態調用。

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    virtual void print() {
        cout << "Parent:: print()" << endl;
    }
};

class Child : public Parent
{
public:
    void print() {
        cout << "Child:: print()" << endl;
    }
};

class GrandSon : public Child
{
    string name;
public:
    GrandSon(char* n_name)
    {
        name = string(n_name);
    }
    void print()
    {
        cout << "GrandSon::print() :" << name << endl;
    }
};

void how_to_print(Parent* p)
{
    p->print();
}

int main()
{
    GrandSon gson1("jason");
    how_to_print(reinterpret_cast<Parent*>(&gson1));
    Parent* pgson1 = reinterpret_cast<Parent*>(&gson1);

    cout << endl;

    GrandSon gson2("polly");
    Parent* pgson2 = reinterpret_cast<Parent*>(&gson2);
    how_to_print(pgson2);

    cout << endl;
    // 下面是拓展實驗
    Parent* gson_current = pgson1;
    how_to_print(gson_current);

    return 0;
}

爺爺類是非抽象類,實現了自己的virtual的方法A,且父類也實現了自己的virtual的方法A,且子類也實現了自己的virtual的方法A, 此時, 當爺爺類指針指向孫類對象,依然具備多態特性。 

 

最終結論:

只要調用的成員函數自從爺爺類開始就是virtual修飾的,使用爺爺類的指針指向孫類對象時,就支援多態調用。 

如果你需要一個精簡版理解,那麼你只需要理解:

多態調用的精髓在於使用了virtual關鍵字。

 

 

 

 

 

 

.