您的位置:首页 > 房产 > 建筑 > 企业服务平台公众号_工作计划书如何写_做推广公司_网址域名大全

企业服务平台公众号_工作计划书如何写_做推广公司_网址域名大全

2025/7/3 4:43:21 来源:https://blog.csdn.net/m0_62342492/article/details/144158699  浏览:    关键词:企业服务平台公众号_工作计划书如何写_做推广公司_网址域名大全
企业服务平台公众号_工作计划书如何写_做推广公司_网址域名大全

对基类中的方法进行重写;
主要是通过继承机制 + V 表实现;
虚函数的引入与不加入虚函数的主要区别在于 动态多态性。通过将 Entity 类的 GetName 函数声明为 virtual,可以实现 运行时多态,这意味着程序会根据对象的实际类型调用相应的函数,而不是根据指针或引用的类型调用函数。

1. 没有虚函数的情况

如果你不使用虚函数(即 Entity 类中的 GetName 不是 virtual),则即使 Entity 的指针指向了 Player 对象,调用 GetName() 时,依然会执行 Entity 类中的 GetName() 函数。也就是说,调用的是编译时决定的函数,而不是运行时根据实际对象类型选择的函数。

举个例子:

class Entity
{
public:std::string GetName() { return "Entity"; }  // 非虚函数
};class Player : public Entity
{
private:std::string m_Name;
public:Player(const std::string& name) : m_Name(name) {}std::string GetName() { return m_Name; }  // 不会覆盖 Entity 中的 GetName
};void PrintName(Entity* entity)
{std::cout << entity->GetName() << std::endl;  // 总是调用 Entity::GetName()
}int main()
{Entity* e = new Entity;PrintName(e);  // 输出 "Entity"Player* p = new Player("Cherno");PrintName(p);  // 依然输出 "Entity",因为没有虚函数
}

在这种情况下,PrintName(p) 也会输出 "Entity",即使 p 实际上指向的是一个 Player 对象。

2. 引入虚函数后的情况

GetName 函数声明为 virtual 时,C++ 会使用 虚函数表(vtable) 来确定调用哪个函数。虚函数表在运行时动态决定哪个类的版本的 GetName 被调用。因此,当你调用 entity->GetName() 时,程序会根据实际指向的对象类型(无论是 Entity 还是 Player)调用相应的函数。

修改代码后,程序的行为会有所不同:

class Entity
{
public:virtual std::string GetName() { return "Entity"; }  // 声明为虚函数
};class Player : public Entity
{
private:std::string m_Name;
public:Player(const std::string& name) : m_Name(name) {}std::string GetName() override { return m_Name; }  // 重写虚函数
};void PrintName(Entity* entity)
{std::cout << entity->GetName() << std::endl;  // 运行时多态,调用正确的函数
}int main()
{Entity* e = new Entity;PrintName(e);  // 输出 "Entity"Player* p = new Player("Cherno");PrintName(p);  // 输出 "Cherno",因为 GetName 被 Player 重写了
}

现在,程序会根据指针的实际类型来选择调用的 GetName 函数:

  • PrintName(e) 输出 Entity,因为 eEntity 类型的对象。
  • PrintName(p) 输出 Cherno,因为 p 实际上指向的是 Player 类型的对象,GetNamePlayer 重写了。

3. 虚函数的工作原理

在 C++ 中,虚函数的工作原理如下:

  1. 虚函数表(vtable): 每个含有虚函数的类都会生成一个虚函数表,虚函数表存储了类中所有虚函数的地址。在创建对象时,编译器会为每个类对象(包括派生类)设置一个指向该类虚函数表的指针。

  2. 运行时决定: 在调用虚函数时,程序会根据对象的实际类型(即动态类型)来选择虚函数表中的函数地址,进而调用正确的函数。这个过程称为 动态绑定(dynamic binding)或 运行时多态

    • 如果你使用 Entity* e = new Player("Cherno");,即使指针类型是 Entity*,但由于虚函数的存在,程序会正确调用 Player 类中的 GetName,而不是 Entity 类中的 GetName
  3. 虚析构函数: 虚函数不仅可以使类支持多态,还可以使类支持正确的析构过程,避免内存泄漏。例如,Entity 类应该将析构函数声明为虚拟函数,以确保删除 Player 类型的对象时能正确调用 Player 的析构函数。

    class Entity
    {
    public:virtual ~Entity() {}  // 虚析构函数
    };
    

总结

  • 没有虚函数:如果不使用虚函数,基类指针指向派生类对象时,调用的会是基类中的函数,无法实现多态。
  • 使用虚函数:如果使用虚函数,基类指针指向派生类对象时,调用的会是派生类中的函数,实现了动态多态。
  • 弊端:虚函数有着额外的内存消耗(存储V表),以及额外的查询查询时间,对于cpu很差的嵌入式设备可能会有影响
  • 好处:实现了同一函数对于不同对象引用时候的不同方法;

下一节

纯虚函数

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com