Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 按值调用时的隐式转换和多态性_C++_Gcc_Constructor_Polymorphism_Implicit Conversion - Fatal编程技术网

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

C++ 按值调用时的隐式转换和多态性,c++,gcc,constructor,polymorphism,implicit-conversion,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 (Speci

考虑以下场景: 一些多态类:

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;
}
void someFunc(SpecificClass sc){sc.foo();}//传递值:我要复制它!
int main()
{
CommonClass comCl;

someFunc(comCl);//
someFunc
需要类型为
SpecificClass
的参数,并且您提供类型为
CommonClass
的参数。因为您已经定义了转换构造函数

SpecificClass::SpecificClass(CommonClass &)
SpecificClass::SpecificClass(SpecificClass &)
这种转换可以隐式执行,到目前为止,这非常好

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

但是,问题出现在下一步:新转换的
SpecificClass
类型的对象现在需要复制到
someFunc
的函数参数
sc
中。为此,需要为
SpecificClass
创建一个复制构造函数,该构造函数可以采用右值(这就是新转换的
SpecificClass
对象,因为它是临时对象)

您的副本构造函数

SpecificClass::SpecificClass(CommonClass &)
SpecificClass::SpecificClass(SpecificClass &)
声明为接受非常量左值引用,该引用无法绑定到临时引用。因此必须将其更改为

SpecificClass::SpecificClass(const SpecificClass &)
这是声明副本构造函数的常用方法


还有一件事我忍不住要注意:您有一个函数
someFunc
,该函数只能在非常特定类型的对象上调用,但您可以在常规(基类?)上调用它类型。很明显,这可以按照您描述的方式工作,但在许多方面它是违反直觉的,并且与面向对象编程的原则不太一致。这也让我想知道“特定”对象实际上是如何从“公共”对象创建的,即转换构造函数的实际功能。直觉上,我假设作为输入提供的“公共”对象缺少创建“特定”对象的“特定”信息


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

您的构造函数采用
CommonClass&
,但您需要一个接受
const CommonClass&
的构造函数您正在尝试将右值绑定到非常量左值引用。您确切的意思是什么部分将是右值?我在这里没有看到任何常量?我在Specific类中为commonClass添加了一个常量构造函数。仍然是相同的错误!但现在又有一个“候选项”;)是的,您还需要在普通的复制构造函数中使用
const specific class&
。精彩的解释。感谢您的洞察力!太糟糕了,本来只需要调用一个构造函数(而不是通过“可能的优化”)!有没有办法通过在函数调用中使用构造函数来实现这一点?所有这些类都只保存我从某个串行通信设备获得的一个c字符串。我查看、识别并将它们传递给一个特定的回调函数(someFunc)它们需要存在其他特定getter和setter的特定类,因此可以操纵字符串中编码的值。@PhilippMichalski Hmmm。重新搜索优化(即确保只执行一个副本,而不是一个用于转换,一个用于函数调用):我可能错了,但我看不出有任何方法可以保证这一点。(尽管如此,我非常确定GCC,甚至4.1,至少在
--O2
--O3
中执行了这种优化。它抱怨缺少副本构造函数的事实并不意味着它没有优化代码。它抱怨是出于形式上的原因。)我的GCC的“优化级别”实际上是‘-0’,所以我不能指望:-d我不知道为什么,但是它是由我的PLC的供应商提供的默认值,我不能改变它。我有时会问他们…我假设它是他们的第一个原型PLC可编程的C++,这也可以解释为什么它只与GCC 4.1.2(或2.95.3)一起工作。…好的…我必须说,如果你追求速度,那就不好了。在这种情况下,避免这一个副本可能是你最小的问题。但是,你可能想检查是否调用了第二个副本构造函数,或者现在(例如,通过向其中添加打印语句)。如果是,并且您不希望这样做,恐怕您必须为要复制的每个数据类型制作一个单独版本的
someFunc
。但是,将其定义为模板将帮助您保存一些键入。