最近学习C++多态及子类内存结构,有一些理解与看法,记录下来
1.多态产生,虚函数,虚函数指针,虚函数表
这一部分不详细描述,个人参考的书籍是Siddhartha Rao的<21天学通C++>的第11章:多态
了解了编译器利用虚函数表与对象的虚函数指针来实现多态的机制
觉得比较好的文章就记在下面
【转】:https://blog.csdn.net/jiangnanyouzi/article/details/3720807
2.自己的一些思考
Siddhartha Rao:在函数声明中, virtual 意味着当基类指针指向派生对象时,通过它可调用派生类的相应函数
实际上不管有没有出现virtual关键字,基类指针指向子类对象时都发生了一次隐式的强转,即是说基类指针变量的值仍然与子类对象地址的值相同(子类对象第一个字节的地址编号),但是偏移量不同。
所以在没有virtual关键字的时候经过隐式强转,基类指针变量实际指向的是一个基类的对象实例,那么调用对应的方法等同于调用基类实例的方法
然而在有virtual关键字的时候也要经过隐式强转,由于编译器会给子类对象分配一个虚函数表指针,虽然基类指针指向的是一个基类对象实例,但是虚函数指针所指向的虚函数表中的函数却是子类的函数,实现了基类指针调用派生类函数
自己验证的代码如下:
root@ubuntu:/lianxi/lianxi_c++/duotai# g++ 11.1\ InvokingSwimUsingFishPtr.cpp
root@ubuntu:/lianxi/lianxi_c++/duotai# ./a.out
Tuna swims!
lets see InputFish->Swim()
Fish swims!
lets see p->Swim()
Tuna swims!
root@ubuntu:/lianxi/lianxi_c++/duotai#
1 #include <iostream>
2 #include <stdio.h>
3
4 using namespace std;
5
6 class Fish
7 {
8 public:
9 void Swim()
10 {
11 cout << "Fish swims!" << endl;
12 }
13 };
14
15 class Tuna:public Fish
16 {
17 public:
18 void Swim()
19 {
20 cout << "Tuna swims!" << endl;
21 }
22 };
23
24 void MakeFishSwim(Fish* InputFish)
25 {
26 printf("lets see InputFish->Swim()\n");
27 InputFish->Swim();//Fish swims!
28 putchar(10);
29 printf("lets see p->Swim()\n");
30 Tuna* p = NULL;
31 p = (Tuna*)(InputFish);
32 p->Swim();//Tuna swims!
33 return;
34 }
35
36 int main()
37 {
38 Tuna myDinner;
39
40 myDinner.Swim();
41
42 MakeFishSwim(&myDinner);
43
44 return 0;
45 }