资料汇集:
https://www.runoob.com/cplusplus/cpp-inheritance.html
https://blog.youkuaiyun.com/qq_35644234/article/details/52825311
继承
C++的面向对象编程是一个非常大的泛式编程,其中类之间的继承是它的一个基本方面。
虚函数
#include <iostream>
class Entity
{
public:
std::string Getname() {
return "Entity";
}
};
class Player : public Entity
{
public:
Player(const std::string& name) : m_name(name) {};
std::string Getname() {
return m_name;
}
private:
std::string m_name;
};
int main()
{
Entity* e = new Entity;
std::cout << e->Getname() << std::endl;
Player* p = new Player("Dada");
std::cout << p->Getname() << std::endl;
std::cin.get();
}
运行结果:
#include <iostream>
class Entity
{
public:
std::string Getname() {
return "Entity";
}
};
class Player : public Entity
{
public:
Player(const std::string& name) : m_name(name) {};
std::string Getname() {
return m_name;
}
private:
std::string m_name;
};
void PrintName(Entity* entity)
{
std::cout << entity->Getname() << std::endl;
}
int main()
{
Entity* e = new Entity;
PrintName(e);
Player* p = new Player("Dada");
PrintName(p);
std::cin.get();
}
运行结果:
我们希望C++能够意识到PrintName§调用的Getname()函数实际上是Player中的Getname——这就引出了虚函数的概念。
虚函数实际上引入了一种叫做 Dynamic Dispatch(动态联编)的东西,它通常通过V-Table(虚函数表)来实现编译。v表实际上就是一个表,它包含基类中所有虚函数的映射,这样我们就可以通过它映射到正确的复写(override)函数,在用复写函数之前必须将基类中的基函数标记为虚函数。
虚函数的实现:
在基类的函数前加上 virtual 即可。
#include <iostream>
class Entity
{
public:
virtual std::string Getname() {
return "Entity";
}
};
class Player : public Entity
{
public:
Player(const std::string& name) : m_name(name) {};
std::string Getname()
{
return m_name;
}
private:
std::string m_name;
};
void PrintName(Entity* entity)
{
std::cout << entity->Getname() << std::endl;
}
int main()
{
Entity* e = new Entity;
PrintName(e);
Player* p = new Player("Dada");
PrintName(p);
std::cin.get();
}
这样就可以告诉编辑器,如果这个函数在派生类中被重写了,生成v表并指向正确的映射函数。
运行结果:
在C++11中还引入了一个新特性,就是在复写函数上标记上override,这样可以在一定程度上避免映射错误。 (注意标记的位置)
#include <iostream>
class Entity
{
public:
virtual std::string Getname() {
return "Entity";
}
};
class Player : public Entity
{
public:
Player(const std::string& name) : m_name(name) {};
std::string Getname() override {
return m_name;
}
private:
std::string m_name;
};
void PrintName(Entity* entity)
{
std::cout << entity->Getname() << std::endl;
}
int main()
{
Entity* e = new Entity;
PrintName(e);
Player* p = new Player("Dada");
PrintName(p);
std::cin.get();
}