考虑以下场景: 一些多态类:
struct iClass
{
virtual ~iClass(){}
};
struct CommonClass : public iClass
{
char str[128];
CommonClass() { ... }
...
};
struct SpecificClass : public iClass
{
char str[32];
SpecificClass () { ... }
SpecificClass (SpecificClass& src) { strcpy(...); ... }
SpecificClass (CommonClass& src) { strcpy(...); ... }
SpecificClass (const CommonClass& src) { strcpy(...); ... }
void foo() { ... }
};
还有一个功能:
void someFunc(SpecificClass sc) { sc.foo(); } // pass by value: i want it copied!
int main ()
{
CommonClass comCl;
someFunc(comCl); // <- Error: no matching function for call to 'SpecificClass::SpecificClass(SpecificClass)' NOTE: no &
SpecificClass specCl(comCl);
someFunc(specCl); // Works normal, but the str gets copied double times this way, isnt it?
return 0;
}
为什么编译器不允许在第一个函数调用中从 CommonClass 到 SpecificClass 的转换,尽管无论如何都会在调用中构造一个新的 SpecificClass 并且有一个用于此特定转换的构造函数? 为什么我会收到这个奇怪的错误消息?在没有引用的情况下调用复制构造函数? 谁能分享一些关于这个问题的见解?
顺便说一句,我必须使用 gcc 4.1.2
最佳答案
someFunc
需要一个 SpecificClass
类型的参数,并且您提供一个 CommonClass
类型的参数。由于您已经定义了转换构造函数
SpecificClass::SpecificClass(CommonClass &)
这种转换可以隐式执行,到目前为止效果很好。
[但请注意,您的转换构造函数采用非常量引用,这在这里起作用,因为您实际上为它提供了左值 - 但是,一般来说,我假设将转换构造函数的参数视为 const CommonClass &
通常更好(因为从一种类型到另一种类型的转换通常不会改变原始类型)。]
但是,问题出现在下一步中:新转换的SpecificClass
类型的对象现在需要复制到函数参数sc
中someFunc
的 >。为此,您需要 SpecificClass
的复制构造函数,它可以接受右值(这就是新转换的 SpecificClass
对象,因为它是临时的)。
你的复制构造函数
SpecificClass::SpecificClass(SpecificClass &)
被声明为采用非常量左值引用,该引用不能绑定(bind)到临时值。所以你必须将其更改为
SpecificClass::SpecificClass(const SpecificClass &)
解决问题。无论如何,这就是声明复制构造函数的常用方法。
我不禁注意到的另一件事是:您有一个函数 someFunc
,该函数仅在非常特定类型的对象上调用。然而,您将其称为通用(基类?)类型。显然,这可以按照您所描述的方式工作,但它在很多方面都违反直觉,并且不符合面向对象编程的原则。这也让我想知道“特定”对象实际上是如何从“公共(public)”对象创建的,即转换构造函数实际上做了什么。直观上,我假设作为输入给出的“通用”对象缺乏创建“特定”对象的“特定”信息。
无论如何,您可能需要重新考虑类层次结构和/或 someFunc
的用途。不过,这些都与您问题中描述的问题没有直接关系。
关于c++ - 按值调用时的隐式转换和多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17229959/