一、多态是什么?
简单来说就是多种状态,去完成某个行为的时候,不同对象就完成时会产生不同的形态,可以分为静态多态和动态多态
静态多态是:重载和模板,在编译阶段来实现
动态多态是:可以使用虚函数来实现
动态多态实现条件:
1、必须对虚函数进行重写
2、父类的指针或者引用去调用对象。
1、类里面的成员函数
1、1虚函数
被virtual关键字修饰的成员函数,通过指针的指向的对象去调用虚函数,虚函数必须有this指针
几种情况分析如下:
静态成员函数不能是虚函数(因为不存在this指针)
构造函数不能成为虚函数(虚函数指针是在构造函数初始化列表阶段初始化)
析构函数可以是虚函数,且最好把基类的析构函数定义为虚函数(析构函数重写的名字不能一致)
示例如下:
class A
{
public:
virtual ~A()
{
cout << "~A()" << endl;
}
};
class B : public A
{
public:
virtual ~B()
{
cout << "~B()" << endl;
}
};
实现效果

1、2三种状态
重载:在同一个作用域中只需要函数名相同,参数不同
重写:两个函数分别在基类和派生类,函数名/参数/返回值必须相同(协变例外),两个函数得是虚函数
重定义:两个函数分别在基类和派生类中,函数名相同,不构成重写就是重定义
三者关系如下所示

1、3 虚函数的重写
重写的时候派生类被重写的虚函数也可以没virtual修饰
代码如下(示例):
class A
{
public:
virtual void f()
{
cout << "A::f()" << endl;
}
};
class B : public A
{
public:
virtual void f()
{
cout << "B::f()" << endl;
}
};
1、4 多态的实现
代码如下(示例):
int main()
{
A a;
B b;
A* ptr1 = &a;
A* ptr2 = &b;
ptr1->f();
ptr2->f();
return 0;
}
实现结果

二、虚函数表
这里容易考察一个对象有多大
class A
{
public:
virtual void f()
{
cout << "A::f()" << endl;
}
public:
int _a;
};
int main()
{
A a;
printf("%d\n", sizeof(a));
}

(在32位平台下)首先会存在一个虚函数表指针,再加上类成员,共8个字节
虚函数表
是存储虚函数指针的一个数组,在编译阶段就产生,一般情况存储在代码段

同一类,不同对象公享一张虚表
不同类,各有一张虚表


第一个是虚函数指针
第二个是虚函数指针数组的结尾空指针标志
多继承情况下会存在多张虚函数表,并且子类没有重写的虚函数会放在第一个虚函数表末尾

文章详细介绍了多态的概念,包括静态多态和动态多态,重点讲解了动态多态如何通过虚函数实现。文章讨论了虚函数的特性,如不能在静态成员函数和构造函数中使用,并强调析构函数应为虚函数。还阐述了重载、重写和重定义的区别,并给出了虚函数重写的例子。最后,探讨了虚函数表的作用以及对象大小与虚函数表的关系。
1334

被折叠的 条评论
为什么被折叠?



