前言
众所周知C++是门面向对象的语言,其中三大特性是继承、封装和多态。多态又分为动态和静态多态两种,其中静态多态指重载和隐藏,而动态多态指虚函数机制。本篇主要介绍动态多态的虚函数机制。
一、虚函数机制
? 虚函数是指基类中使用virtual关键字修饰的成员函数,如果基类未实现该虚函数,则成为抽象类,抽象类不能直接实例化,并且如果派生类继承虚函数,必须实现基类的虚函数才能实例化,这个实现过程也叫重写。 ?如何体现其动态特性能呢?其实是因为面向对象编程的过程中,如果希望基类指针指向不同派生类时,希望其可以调用不同派生类中的函数而不是基类的函数,可以通过将基类中的函数声明为虚函数达成。 ?具体实现机制如下:编译器为每个具有虚函数的基类生成一个虚函数表,不同类有不同的虚函数表,同一个类的不同对象共享一个虚函数表。继承这种基类的派生类在实例化时,会多出一个虚表指针指向对应类的虚函数表,因此即使派生类被转化成基类指针,其虚表指针依然能帮助指向对应派生类的函数
二、C++实现虚函数
class ISpearker
{
protected:
size_t id;
public:
ISpearker(size_t id) :id(id) {}
virtual void speak() = 0;
virtual void walk() = 0;
};
class Dog : public ISpearker
{
public:
Dog() : ISpearker(0) {}
void speak()
{
printf("id: %d, dogs say woof \n", this->id);
}
void walk()
{
printf("id: %d, dog is walking\n", ((__dog*)ptr)->id);
}
};
class Human : public ISpearker
{
public:
Human() : ISpearker(1) {}
const char* name;
void speak()
{
printf("id: %d, human %s say hello \n", this->id, this->name);
}
void walk()
{
printf("id: %d, human %s is walking \n", this->id, this->name);
}
};
int main()
{
Dog dog;
Human human;
ISpearker* speaker_dog = static_cast<ISpearker*>(&dog);
ISpearker* speaker_human = static_cast<ISpearker*>(&human);
speaker_dog->speak();
speaker_human->speak();
speaker_dog->walk();
speaker_human->walk();
}
运行结果:
三、C实现虚函数
struct SpeakerTable
{
void(*speak)(void* ptr);
void(*walk)(void* ptr);
};
struct __ispeaker
{
const SpeakerTable* vfptr;
size_t id;
};
struct __dog
{
const SpeakerTable* vfptr;
size_t id;
};
struct __human
{
const SpeakerTable* vfptr;
size_t id;
const char* name;
};
void __dog_speak(void* ptr)
{
printf("id: %d, dogs say woof \n", ((__dog*)ptr)->id);
}
void __human_speak(void* ptr)
{
__human* human = (__human*)ptr;
printf("id: %d, human %s say hello \n", human->id, human->name);
}
void __dog_walk(void* ptr)
{
printf("id: %d, dog is walking\n", ((__dog*)ptr)->id);
}
void __human_walk(void* ptr)
{
__human* human = (__human*)ptr;
printf("id: %d, human %s is walking \n", human->id, human->name);
}
const static SpeakerTable __dogSpeakerTable = { __dog_speak, __dog_walk };
const static SpeakerTable __humanSpeakerTable = { __human_speak, __human_walk };
__dog* createDog(size_t id)
{
__dog* dog = (__dog*)malloc(sizeof __dog);
dog->vfptr = &__dogSpeakerTable;
dog->id = id;
return dog;
}
__human* createHuman(size_t id)
{
__human* human = (__human*)malloc(sizeof __human);
human->vfptr = &__humanSpeakerTable;
human->id = id;
human->name = "tom";
return human;
}
void test()
{
__dog* dog = createDog(0);
__human* human = createHuman(1);
__ispeaker* idog = (__ispeaker*)dog;
__ispeaker* ihuman = (__ispeaker*)human;
idog->vfptr->speak((__dog*)idog);
ihuman->vfptr->speak((__human*)ihuman);
idog->vfptr->walk((__dog*)idog);
ihuman->vfptr->walk((__human*)ihuman);
}
int main()
{
test();
}
运行结果:
总结
深化对C++虚函数机制
|