【问题标题】:Redefined virtual function call重新定义虚函数调用
【发布时间】:2022-12-13 10:20:56
【问题描述】:

考虑:

#include <iostream>

class Base
{
public:
    virtual void foo() { std::cout << "Base::foo()\n"; };

};

class Derived : public Base
{
public:
    void foo() override 
    {
        std::cout << "Derived::foo()\n";  
        Base::foo();
    }

};

int main()
{
    Derived obj;
    obj.foo();

    return 0;
}

这是我的代码。为什么我可以在衍生的类,如果我已经重新定义它衍生的班级。为什么编译器不删除类中的 Base::foo衍生的重新定义后?

【问题讨论】:

  • “为什么我可以在派生类中调用 Base::foo()”——嗯,因为这就是 C++ 的工作方式……我建议你选择a few good books 并实际学习这门语言(顺便说一句;这需要一些时间(3-5) 年)。
  • 像这样调用Base::foo(),成员函数调用没有使用动态调度机制。
  • 你的头衔出卖了你——你说“重新定义”。没有任何内容被重新定义,这两个功能仍然存在,并且就像您所看到的那样在各种不同的上下文中可用。
  • 一个问题是可能有一个子类或派生类需要 Base::foo() 类。由于Base方法只有一个副本,删除Base::foo()方法并没有真正节省多少。

标签: c++ polymorphism virtual-functions


【解决方案1】:

“为什么编译器在重新定义后不删除派生类中的 Base::foo”

因为那不是 virtual 和 override 所做的。当您为基类函数提供覆盖时,您不会替换它。您正在为该函数定义一个新版本。基类的实现继续存在并且可以访问。

考虑以下代码。有人仍然可以使用 Base 对象,并且行为不应更改,因为 Derived 存在。无论Derived 是否存在,base_obj.foo() 的输出都应该继续为"Base::foo()"。 :

#include <iostream>

class Base
{
public:
    virtual void foo() { std::cout << "Base::foo()
"; }
};

class Derived : public Base
{
public:
    void foo() override { std::cout << "Derived::foo()
"; }
};

int main()
{
    Derived obj;
    obj.foo();

    Base base_obj;
    base_obj.foo();

    return 0;
}

还要考虑多个类可以从 Base 派生。我可以添加一个 class MyClass : public Base 和它自己的 foo() 版本,它不应该干扰 Base 或 Derived 对象的行为。

如果重写一个成员函数会导致基成员函数被完全替换或删除,那么如果不仔细阅读从代码派生的每个类,就几乎不可能对代码进行推理。除非您的 IDE 为此提供工具,否则它意味着阅读所有代码库。这会使使用多态性的 C++ 代码极难理解。

【讨论】:

  • 但是在 Derived 类中覆盖 foo() 之后我不明白,Derived 是否包含带有 Base::foo() 实现的 foo() 函数?
  • @Gevv Derive公开继承自Base。所以 Derive 可以用来调用任何 Base 成员函数,如果你问得好的话。如果你写 obj.Base::foo(); 那么它会调用函数的 Base 版本,因为你明确要求它。请注意,类对象不“包含”任何函数。函数不会增加对象的大小,对象不存储函数是它们内存表示的一部分。函数不是对象,它们只是描述一种行为。它们与对象静态分离。
  • 说派生我的意思是派生类而不是派生对象
  • 那么是的,Derived 提供了Base 提供的每个public 成员函数。这包括派生类型覆盖的函数版本。覆盖允许您定义基函数的新版本,并在函数名称不合格时默认调用它。但是基本版本仍然可以访问。但实际上,很少有人会选择显式调用 virtual 成员函数的基本版本。
猜你喜欢
  • 2020-02-12
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 2010-11-15
  • 2013-07-03
  • 2012-02-06
  • 2017-06-08
相关资源
最近更新 更多