虚函数

时间:2011-04-18 18:06:16

标签: c++ virtual-functions

我对C ++虚函数有疑问。

派生类(DerivedAlgo)实现虚函数(BaseAlgo::process),但通过使用DerivedData类型作为输入参数而不是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);

我非常感谢你的任何投入。谢谢!

3 个答案:

答案 0 :(得分:1)

你的第一个例子不能在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)版本,而不是覆盖它。覆盖虚函数时,不应更改函数签名。

答案 1 :(得分:1)

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

当我编译它时(在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中声明   class派生,直接派生或   成员之间的间接来自Base   函数vf具有相同的名称和   与Base :: vf相同的参数列表是   声明,然后Derived :: vf也是   虚拟的(无论是否如此   宣布)并覆盖97)   基:: VF。

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

如果您从未真正调用派生类,那么您的编译器可能无法彻底检查您的代码。

答案 2 :(得分:0)

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