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