我有一个关于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);我真的很感谢你的任何意见。谢谢!
发布于 2011-04-19 02:30:11
您的第一个示例不能在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&)如果像我的例子这样的东西确实编译了,那么几乎可以肯定你的编译器有buggy。
您的第二个示例将被编译,因为它覆盖了抽象函数。第一个调用将调用基础数据版本,而第二个调用将调用process的派生版本。
请注意,在第一个示例中,您隐藏了函数的process(base)版本,而不是覆盖它。在重写虚函数时,不应该更改函数签名。
发布于 2011-04-19 02:31:12
你确定你没有得到一个编译器错误吗?
当我编译这段代码(在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/如果在类Base和派生类(直接或间接派生自Base )中声明了虚拟成员函数vf,则声明了与Base::vf具有相同名称和相同参数列表的成员函数vf,则Derived::vf也是虚拟的(无论是否如此声明),并且它是overrides97) Base::vf。
在派生类中声明重写的唯一余地是协变返回类型。
如果您从未实际调用过派生类,则编译器可能没有彻底检查您的代码。
发布于 2011-04-19 02:34:38
你的问题是c++不支持double dispatch。您需要在BaseAlgo类上使用Visitor pattern。
https://stackoverflow.com/questions/5706981
复制相似问题