通过实验了解C++中的类是如何实现多态

来源:互联网 发布:html5 php实现微博 编辑:程序博客网 时间:2024/05/16 12:51

通过实验了解C++中的类是如何实现多态的

c++是面向对象中最经典的语言之一,类是c++实现面向对象范式的基本元素,面向对象的三原则封装、继承、多态都需要类的特性支持。所以理解类的一些基本特点,如构造、析构、继承、虚函数等很重要。下面通过一个简单的测试实验来帮助理解记忆这些重要的过程和特点。

涉及到的点有:

  • 在派生类中覆盖虚函数实现多态
  • 类的对象在定义时的静态绑定和运行时的动态绑定的概念
  • 派生类构造析构时相关构造析构函数的调用过程
  • 基类通过动态转换到派生类
  • 多重继承的基类中有同名非虚函数时如何无歧义调用

几点基本的总结:

基类指针指向派生类时,调用基类中的非虚函数和没有在派生中覆盖的函数时会调用基类自身的函数,但对于有在派生类中覆盖过的基类的虚函数,会调用派生类的实现。因为这个原因基类的析构函数一般要定义成虚的,这样在用基类指针实现多态的情况下析构时才会调用派生的析构函数来释放派生类中申请的空间,否则只会释放基类自己申请的空间。另外不能通过指针调用基类中没有而在派生中定义的函数,无论派生类中的函数是否为虚的。

多重继承的类在构造时按声明继承基类的顺序依次调用基类的构造函数,最后再调用自己的构造函数。析构时调用顺序相反。

dynamic_cast动态转换时会进行运行时类型检查,类型安全(待转换的指针的动态绑定的类型与要转换成的类型一致)的转换可以得到想要的指针,否则只能得到空指针NULL。转换后得到的指针与原来的指针指向的地址一致,只是指针类型不同。

详细的内容请阅读下面的代码和执行后的输出结果。对应代码的执行过程和输出的顺序可以更清楚的看到这些要点。


下图是实验中类的关系图
测试中类的关系图

接下来是实验中类的定义。

#include <iostream>using namespace std;class Father {    public:    Father() {        cout<<"construct Father"<<endl;    }    virtual void f() {        cout<<"Father::f()"<<endl;    }    void g() {        cout<<"Father::g()"<<endl;    }    void j() {        cout<<"Father::j()"<<endl;    }    virtual ~Father() {        cout<<"destruct Father"<<endl;    }    };class Mother {    public:    Mother() {        cout<<"construct Mother"<<endl;    }    virtual void f() {        cout<<"Mother::f()"<<endl;    }    void g() {        cout<<"Mother::g()"<<endl;    }    virtual void h() {        cout<<"Mother::h()"<<endl;    }    void j() {        cout<<"Mother::j()"<<endl;    }    virtual ~Mother() {        cout<<"destruct Mother"<<endl;    }    };class Child1 : public Father, public Mother {    public:    Child1() {        cout<<"construct Child1"<<endl;    }    void f() {        cout<<"Child1::f()"<<endl;    }    void g() {        cout<<"Child1::g()"<<endl;    }    void h() {        cout<<"Child1::h()"<<endl;    }    void k() {        cout<<"Child1::k()"<<endl;    }    ~Child1() {        cout<<"destruct Child1"<<endl;    }      };class Child2 : public Father, public Mother {    public:    Child2() {        cout<<"construct Child2"<<endl;    }    ~Child2() {        cout<<"destruct Child2"<<endl;    }      };class GrandSon : public Child1 {    public:    GrandSon() {        cout<<"construct GrandSon"<<endl;    }    void f() {        cout<<"GrandSon::f()"<<endl;    }    void g() {        cout<<"GrandSon::g()"<<endl;    }        ~GrandSon() {        cout<<"destruct GrandSon"<<endl;    }      };

这段代码是实验的内容:

int main() {    Father* b1 = new Father();    Father* b2 = new Child1();    Father* b3 = new GrandSon();    Mother* m = new Mother();    Father* b4 = new Child2();    Mother* b5 = new Child2();    b1->f(); //Father::f()    b2->f(); //Child1::f()    b3->f(); //GrandSon::f()    b1->g(); //Father::g()    b2->g(); //Father::g()    b3->g(); //Father::g()    b4->f(); //Father::f()    b5->f(); //Mother::f()    //b2->k(); //error: 'class Father' has no member named 'k'    Child1* boy = dynamic_cast<Child1*>(b2); //(int*)boy == (int*)b2     if (boy) {        boy->k();  //Child1::k()    }    else {        cout<<"b2 can't be casted to Child*"<<endl;    }    Child1* girl = dynamic_cast<Child1*>(b4); //girl == NULL    if (girl) {        girl->k();    }    else {        cout<<"b4 can't be casted to Child1*"<<endl;    }    //b2->h();  // error: 'class Father' has no member named 'h'    //b3->h();  // error: 'class Father' has no member named 'h    Mother* m1 = dynamic_cast<Mother*>(b2);    Mother* m2 = dynamic_cast<Mother*>(b3);    m->h(); // Mother::h()     m1->h(); // Child1::h()     m2->h(); // Child1::h()     GrandSon* g1 = dynamic_cast<GrandSon*>(b3);    if ((int*)g1 == (int*)b3) {        cout<<"g1 and b3 are the same object"<<endl;    }    else {        cout<<"g1 is different with b3"<<endl;    }    g1->f(); //GrandSon::f()    g1->g(); //GrandSon::g()    //g1->j(); //error: request for member 'j' is ambiguous    //eliminate the ambiguity    g1->Father::j(); //Father::j()    g1->Mother::j(); //Mother::j()    delete b1;    delete b2;    delete b3;    return 0;}

输出结果为:

construct Father
construct Father
construct Mother
construct Child1
construct Father
construct Mother
construct Child1
construct GrandSon
construct Mother
construct Father
construct Mother
construct Child2
construct Father
construct Mother
construct Child2
Father::f()
Child1::f()
GrandSon::f()
Father::g()
Father::g()
Father::g()
Father::f()
Mother::f()
Child1::k()
b4 can’t be casted to Child1*
Mother::h()
Child1::h()
Child1::h()
g1 and b3 are the same object
GrandSon::f()
GrandSon::g()
Father::j()
Mother::j()
destruct Father
destruct Child1
destruct Mother
destruct Father
destruct GrandSon
destruct Child1
destruct Mother
destruct Father

0 0
原创粉丝点击