首页
学习
活动
专区
圈层
工具
发布

虚函数
EN

Stack Overflow用户
提问于 2011-04-19 02:06:16
回答 3查看 622关注 0票数 1

我有一个关于C++虚拟函数的问题。

派生类(DerivedAlgo)实现了虚函数(BaseAlgo::process),但通过使用DerivedData类型而不是BaseData作为输入参数,对函数签名进行了一些更改。

尽管基类中有纯粹的抽象函数,但我仍然能够创建DerivedAlgo类的实例,并且编译器没有任何错误。

我只是想知道有没有人知道任何C++规则可以解释下面的代码。

代码语言:javascript
复制
class BaseData{};
class DerivedData: public BaseData{};
class BaseAlgo{
public:
  virtual void process(BaseData& data) = 0;
};
class DerivedAlgo: BaseAlgo{
public:
  virtual void process(DerivedData& data){
    std::cout << "hello world!" << std::endl;
  }
};

在我的另一个示例代码中,我定义了process(DerivedData&)process(BaseData&)

编译器仍然可以运行,而不会出现任何歧义。

代码语言:javascript
复制
class DerivedAlgo{
public:
  virtual void process(DerivedData& data){...}
  virtual void process(BaseData& data){...}
};
BaseData baseData;
DerivedData derivedData;
derivedAlgo.process(baseData);
derivedAlgo.process(derivedData);

我真的很感谢你的任何意见。谢谢!

EN

回答 3

Stack Overflow用户

发布于 2011-04-19 02:30:11

您的第一个示例不能在g++ 4.2上编译。作为参考,我这样做:

代码语言:javascript
复制
#include <iostream>

class BaseData{};
class DerivedData: public BaseData{};
class BaseAlgo{
public:
  virtual void process(BaseData& data) = 0;
};
class DerivedAlgo: BaseAlgo{
public:
  virtual void process(DerivedData& data){
    std::cout << "hello world!" << std::endl;
  }
};

int main()
{
    DerivedAlgo da;

    return 0;
}

结果是这样的:

代码语言:javascript
复制
error: cannot declare variable 'da' to be of abstract type 'DerivedAlgo'
note:   because the following virtual functions are pure within 'DerivedAlgo'
note:  virtual void BaseAlgo::process(BaseData&)

如果像我的例子这样的东西确实编译了,那么几乎可以肯定你的编译器有buggy。

您的第二个示例将被编译,因为它覆盖了抽象函数。第一个调用将调用基础数据版本,而第二个调用将调用process的派生版本。

请注意,在第一个示例中,您隐藏了函数的process(base)版本,而不是覆盖它。在重写虚函数时,不应该更改函数签名。

票数 1
EN

Stack Overflow用户

发布于 2011-04-19 02:31:12

你确定你没有得到一个编译器错误吗?

当我编译这段代码(在MSVC9中)时:

代码语言:javascript
复制
#include <cstdlib>
#include <memory>
#include <iostream>

class BaseData{};
class DerivedData: public BaseData{};
class BaseAlgo{
public:
  virtual void process(BaseData& data) = 0;
};
class DerivedAlgo: BaseAlgo{
public:
  virtual void process(DerivedData& data){
      data;
    std::cout << "hello world!" << std::endl;
  }
};

int main()
{
    DerivedAlgo da;
}

我得到了预期的错误:

代码语言:javascript
复制
1>.\main.cpp(21) : error C2259: 'DerivedAlgo' : cannot instantiate abstract class
1>        due to following members:
1>        'void BaseAlgo::process(BaseData &)' : is abstract
1>        .\main.cpp(9) : see declaration of 'BaseAlgo::process'

这是因为您不能使用不同的参数列表覆盖虚拟:

10.3虚拟函数

2/如果在类Base和派生类(直接或间接派生自Base )中声明了虚拟成员函数vf,则声明了与Base::vf具有相同名称和相同参数列表的成员函数vf,则Derived::vf也是虚拟的(无论是否如此声明),并且它是overrides97) Base::vf。

在派生类中声明重写的唯一余地是协变返回类型。

如果您从未实际调用过派生类,则编译器可能没有彻底检查您的代码。

票数 1
EN

Stack Overflow用户

发布于 2011-04-19 02:34:38

你的问题是c++不支持double dispatch。您需要在BaseAlgo类上使用Visitor pattern

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5706981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档