虚拟功能

发布于 2024-11-01 19:21:24 字数 993 浏览 2 评论 0原文

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

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

尽管基类中有纯抽象函数,我仍然能够创建 DerivedAlgo 类的实例,并且编译器根本不会抱怨。

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

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&)

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

class DerivedAlgo{
public:
  virtual void process(DerivedData& data){...}
  virtual void process(BaseData& data){...}
};
BaseData baseData;
DerivedData derivedData;
derivedAlgo.process(baseData);
derivedAlgo.process(derivedData);

我非常感谢您的任何意见。谢谢!

I have a question regarding to the C++ virtual function.

The derived class (DerivedAlgo) implements the virtual function (BaseAlgo::process) but changes a little bit in the function signature by using the DerivedData type as the input parameter instead of BaseData.

Despite the pure abstract function in the base class, I am still able to create an instance of the DerivedAlgo class and the compiler does not complain at all.

I just wonder anyone knows any C++ rule which can explain the following code.

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;
  }
};

In my another sample code, I define process(DerivedData&) and process(BaseData&).

The compiler can still run through without complaining any ambiguity.

class DerivedAlgo{
public:
  virtual void process(DerivedData& data){...}
  virtual void process(BaseData& data){...}
};
BaseData baseData;
DerivedData derivedData;
derivedAlgo.process(baseData);
derivedAlgo.process(derivedData);

I really appreciate any of your inputs. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橘虞初梦 2024-11-08 19:21:24

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

#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;
}

并得到了这个:

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&)

如果像我的示例确实编译了,那么你几乎肯定有一个有错误的编译器。

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

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

Your first example doesn't compile on g++ 4.2. For reference I did this:

#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;
}

And got this:

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&)

If something like my example did compile then you almost surely have a buggy compiler.

Your second example will compile because it overrides the abstract function. The first call will call the base data version while the second call will call the derived version of process.

Note that in your first example you're hiding the process(base) version of the function, not overriding it at all. You shouldn't change the function signature when overriding virtual functions.

隔岸观火 2024-11-08 19:21:24

您确定没有收到编译器错误吗?

当我编译这个(在 MSVC9 中)时:

#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;
}

我收到预期的错误:

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/ 如果虚拟成员函数 vf 是
在类 Base 和 a 中声明
类派生、直接派生或
间接来自 Base,会员
具有相同名称的函数 vf 和
与 Base::vf 相同的参数列表是
声明,然后 Derived::vf 也是
虚拟(无论是否如此
声明)并覆盖97)
基础::vf。

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

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

Are you sure you're not getting a compiler error?

When I compile this (in MSVC9):

#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;
}

I get the expected error:

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'

This is because you cannot override virtuals with different parameter lists:

10.3 Virtual Functions

2/ If a virtual member function vf is
declared in a class Base and in a
class Derived, derived directly or
indirectly from Base, a member
function vf with the same name and
same parameter list as Base::vf is
declared, then Derived::vf is also
virtual (whether or not it is so
declared) and it overrides97)
Base::vf.

The only leeway you have in declaring overrides in the derived class is with covariant return types.

It's possible your compiler didn't thoroughly check your code if you never actually call the derived class.

月牙弯弯 2024-11-08 19:21:24

你遇到的问题是c++不支持双重调度。您需要在 BaseAlgo 类上使用 访问者模式

the problem you have is that c++ does not support double dispatch. You need to use a Visitor pattern on your BaseAlgo class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文