通过值和多态性调用时的隐式转换

时间:2013-06-21 07:33:37

标签: c++ gcc constructor polymorphism implicit-conversion

请考虑以下情形: 一些多态类:

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

1 个答案:

答案 0 :(得分:3)

someFunc需要SpecificClass类型的参数,并且您提供CommonClass类型的参数。由于您已定义了转换构造函数

SpecificClass::SpecificClass(CommonClass &)

这种转换可以隐式执行,到目前为止很好。

[请注意,你的转换构造函数采用非const引用,这在这里有效,因为你实际上为它提供了左值 - 但是,一般来说,我假设将转换构造函数的参数作为{ {1}}通常更好(因为从一种类型到另一种类型的转换通常不会改变原始类型。)

但是,问题在下一步中发生:现在需要将const CommonClass &类型的新转换对象复制到SpecificClass的函数参数sc中}。为此你需要一个someFunc的拷贝构造函数,它可以使用一个rvalue(这是刚刚转换的SpecificClass对象,因为它是一个临时的。)

您的复制构造函数

SpecificClass
声明

采用非const左值引用,该引用无法绑定到临时值。所以你必须把它改成

SpecificClass::SpecificClass(SpecificClass &)

解决问题。这就是通常声明复制构造函数的常用方法。


另一件事我不禁注意到:你有一个函数SpecificClass::SpecificClass(const SpecificClass &) ,它只能在一个非常特定的类型的对象上调用。你在一般(基类?)类型上调用它。显然,这可以按照你描述的方式工作,但它在许多方面都是违反直觉的,并且与面向对象编程的原理不完全一致。它还让我想知道“特定”对象是如何从“普通”对象实际创建的,即转换构造函数实际上做了什么。直观地说,我假设作为输入给出的“共同”对象缺少“特定”信息来创建“特定”对象。

在任何情况下,您可能都想重新考虑类层次结构和/或someFunc的目的。但是,这些都与您的问题中描述的问题没有直接关系。