【问题标题】:Why base class function is called instead of derived one?为什么调用基类函数而不是派生函数?
【发布时间】:2011-09-16 08:20:46
【问题描述】:

我有一堂课:

class ProjectService : public CProjectT<CSoapMSXMLInetClient>
{
...
}

我在这个派生类中实现了HRESULT ConnectToServer(); 函数。然后我实例化了一个对象并调用了一个函数:

ProjectService project;
project.f1();

现在,f1() 调用 f2()f2() 调用 ConnectToServer()。所有这些函数都是CProjectT&lt;CSoapMSXMLInetClient&gt; 的成员

这里的问题是,CProjectT&lt;CSoapMSXMLInetClient&gt;::ConnectToServer() 被调用而不是 ProjectService::ConnectToServer()。 (我在两个ConnectToServer() 函数的第一行都有一个调试断点。基类中的那个被命中。)

为什么?

【问题讨论】:

  • ConnectToServer函数是用virtual关键字定义的吗?
  • 不,不是。但我有派生类的实例而不是基类。我认为在这种情况下应该调用派生函数
  • @Ali: 会被调用,如果ConnectToServer被定义为virtual,否则编译器根本不会把它放到virtual table中,一直调用base函数。
  • @Ozair:您应该将该评论(附有简短说明)作为答案
  • 这就是虚函数的用途。

标签: c++ inheritance overriding


【解决方案1】:

确保在父类中使用关键字virtual 定义了ConnectToServer 函数。

阅读virtual keyword in C++

【讨论】:

  • 关键字 virtual 告诉编译器将方法放在类的虚拟表中。将使用位于此表中的函数指针调用虚拟方法。该指针被派生类覆盖,派生方法将被执行。
  • 当我使用基类指针或引用调用函数时,这非常有意义。我不会感到惊讶。但是,我使用派生类实例(不是引用或指针,而是值)调用函数。在编译时,编译器知道该对象是派​​生类的一个实例。不是吗?
【解决方案2】:

如前所述,您需要关键字virtual。为什么?因为在您的函数f2()(仅在CProjectT 中定义)中,您调用了函数CProjectT&lt;CSoapMSXMLInetClient&gt;::ConnectToServer()。如果没有virtual 关键字,就无法知道f2() 应该调用派生方法。

如果你想测试:

#include <iostream>

using namespace std;

class Base
{
public:
    void f(){g();} // Wants to call Base::g() if there's no "virtual" keyword
    void g(){cout << "Base" << endl;}
    // virtual void g(){cout << "Base" << endl;}
};
class Derived : public Base
{
public:
    void g(){cout << "Derived" << endl;}
};

int main(int argc, char *argv[])
{
    Derived d;
    d.f();
}

【讨论】:

    【解决方案3】:

    f2() 调用 ConnectToServer(),方法 f2() 定义在 COMPILE TIME。由于 f2() 是 CProject 而不是 ProjectService 的一部分,因此它有两种可能性:
    1。从 CProject 调用硬编码的非虚函数
    2。从虚拟表调用一个函数。

    由于 ConnectToServer() 不是虚拟的,第一个选项将由编译器“选择”。

    就像@Ozair 在第一条评论(和他的回答)中所说:放置 virtual 关键字将使函数变为虚拟,编译器将“选择”第二个选项,并调用派生类。

    (注意函数是从 f2() 调用的,所以编译器无法真正判断这个实例是基类还是派生类)

    【讨论】:

      猜你喜欢
      • 2019-01-09
      • 2015-07-18
      • 2014-01-01
      • 2013-01-28
      • 2022-07-01
      • 2018-05-11
      • 1970-01-01
      • 2021-02-01
      • 1970-01-01
      相关资源
      最近更新 更多