C++ 多态性之向下转型

0、多态原理:

        ((this->vptr)[n])(this),通过this指针找到它的虚指针vptr,再找到它的虚表vtable,取出其中第n个,将其当成函数指针去调用。

        this是啥:所有非静态成员函数的this指向它的调用者,该调用者是个对象;

        vptr是啥:虚指针,指向一个由函数指针构成的数组vtbl;

        n是啥:编译期间计算出的,虚函数在虚表vtbl中的位置;

        总结就是:编译器在vtbl中寻找适当的函数指针。

动态绑定:

(1) p为指向对象的指针,

(2) p为向上转型up cast,结合前一句就是:父类指针指向子类对象,

        代码表示就是下面:

Person* p = new Student;
p->show();
delete p;

(3) p调用的是虚函数;

1、使用dynamic_cast<T>expression 执行向下转型后,调用派生类新增的函数PrintVersion();

2、将基类对象向下转型后,为什么它也能调用派生类新增的函数PrintVersion()呢?

        这个暂时不清楚为什么,以后知道了再补上,按我的目前的理解,基类对象向下转型后,拿到了派生类所有函数的访问权。

        假如猜测合理的话,若是我在此函数中对派生类新增的成员变量进行了修改,会发生什么呢?

        答:编译能过,但运行不过,段错误"Segmentation fault",这是因为父类对象本身并未包含派生类新增的成员变量吗?

        若是哪位大佬路过,还请告知,谢谢。

#include <iostream>
#include <string>
#include <list>
#include <memory>

using namespace std;

class Person
{
public:
        Person(string Name = "hello", int Age = 10)
        :name(Name),age(Age)
        {}

        virtual ~Person()
        {}

        virtual void show() const
        {
                cout << "Call Base class\n";
                cout << "name: " << name << endl;
                cout << "age: " << age << endl;
        }

//private:
protected:
        string name;
        int age;
};

class Student: public Person
{
public:
        Student(string Name = "hello", int Age = 10, int Grade = 100)
        :Person(Name,Age),grade(Grade)
        {}

        virtual ~Student()
        {}

        virtual void show() const
        {
                cout << "Call Derived class\n";
                //Person::show();
                cout << "name: " << name << endl;
                cout << "age: " << age << endl;
                cout << "grade: " << grade << endl;
        }

        void PrintVersion() const
        {
                cout << "C++ version: " << __cplusplus << endl;
        }

private:
        int grade;
};

int main()
{
        list<shared_ptr<Person>> mylist;

        shared_ptr<Person> pPer(new Person("Zhangsan",20));
        shared_ptr<Person> pStu(new Student("Lisi",30,99));

        mylist.push_back(pPer);
        mylist.push_back(pStu);

        list<shared_ptr<Person>>::iterator it = mylist.begin();
        for(; it != mylist.end(); ++it)
        {
                (*it)->show();          /*多态性的体现*/
                //(*it).get()->show();  /*显示转换,与上面那条隐式转换等价*/

                dynamic_cast<Student*>((*it).get())->PrintVersion();  /*向下转型*/
        }

        mylist.clear();

        return 0;
}

执行结果:

XXX:~/Exercise$ g++ myclass.cpp 
XXX:~/Exercise$ ./a.out 
Call Base class
name: Zhangsan
age: 20
C++ version: 201402
Call Derived class
name: Lisi
age: 30
grade: 99
C++ version: 201402

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值