c++ - 按值调用时的隐式转换和多态性

标签 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

最佳答案

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

SpecificClass::SpecificClass(CommonClass &)

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

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

但是,问题出现在下一步中:新转换的SpecificClass类型的对象现在需要复制到函数参数scsomeFunc 的 >。为此,您需要 SpecificClass 的复制构造函数,它可以接受右值(这就是新转换的 SpecificClass 对象,因为它是临时的)。

你的复制构造函数

SpecificClass::SpecificClass(SpecificClass &)

被声明为采用非常量左值引用,该引用不能绑定(bind)到临时值。所以你必须将其更改为

SpecificClass::SpecificClass(const SpecificClass &)

解决问题。无论如何,这就是声明复制构造函数的常用方法。


我不禁注意到的另一件事是:您有一个函数 someFunc ,该函数仅在非常特定类型的对象上调用。然而,您将其称为通用(基类?)类型。显然,这可以按照您所描述的方式工作,但它在很多方面都违反直觉,并且不符合面向对象编程的原则。这也让我想知道“特定”对象实际上是如何从“公共(public)”对象创建的,即转换构造函数实际上做了什么。直观上,我假设作为输入给出的“通用”对象缺乏创建“特定”对象的“特定”信息。

无论如何,您可能需要重新考虑类层次结构和/或 someFunc 的用途。不过,这些都与您问题中描述的问题没有直接关系。

关于c++ - 按值调用时的隐式转换和多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17229959/

相关文章:

c++ - 为什么构造函数调用构造函数会产生奇怪的结果?

c++ - 为什么标准库假定它在全局命名空间中?

windows - 运行gcc失败:在Windows Golang中退出状态1

c++ - decltype 和隐藏外部名称的类成员名称之间的交互

mysql - c++ - 堆对象成员函数访问

java - 创建带参数的构造函数

c++ - GoogleTest 枚举类在 Visual Studio 2012 中不起作用

c++ - OpenGL 4 : Draw with glVertexAttrib

c++ - 复合文字并通过GCC在C++中通过引用传递?

c - C语言中的位数据类型