常量引用、作为参数的构造函数和可编译性

const references, constructors as parameter, and compilability

本文关键字:构造函数 编译 参数 引用 常量      更新时间:2023-10-16

一位同事让我查看他正在编写的一些代码,并遇到了特定行的问题,编译器(g++)会抱怨函数调用没有基于其参数的匹配函数。

在以两种方式解决问题后(一种是将参数移动到其自己的变量并传递它,接下来是更改参数列表以将其作为常量引用),我不得不问这个问题:为什么解决方案是这样的? 正如我的同事所说,我不满足于将其注销,就好像隐藏了一些构造函数细节一样。

结果,我将问题复制并简化为以下内容(使用 g++ -Wall -ansi -pedantic 编译):

class SomeClass
{
   public:
      static void SomeFunction(SomeClass& sc) {}
      static void SomeFunction2(const SomeClass& sc) {}
};
class SomeChild : public SomeClass {};
void testOne(void)
{
   // this compiles
   SomeChild sc = SomeChild();
   SomeClass::SomeFunction(sc);
   // this doesn't compile
   //SomeClass::SomeFunction(SomeChild());
}
void testTwo(void)
{
   // this compiles
   SomeChild sc = SomeChild();
   SomeClass::SomeFunction2(sc);
   // this compiles
   SomeClass::SomeFunction2(SomeChild());
}
int main(void)
{
   testOne();
   testTwo();
   return 0;
}

可能在这里错过了一些非常基本的东西,但是谁能向我解释为什么编译器认为不可编译的行没有匹配的函数调用?

提前谢谢。

原因很简单,临时值(如 SomeChild() 的值)不能绑定到非常量左值引用。虽然这没有深刻的技术原因,但这是一种设计选择:非常量引用通常用于修改被引用的东西,如果那个东西是暂时的,那么修改基本上不会产生持久的影响,这几乎总是逻辑错误。

只需将"SomeFunction2"替换为"SomeFunction":

#include <iostream>
class SomeClass
{
   public:
      static void SomeFunction(SomeClass& sc) { std::cout << "not const" << std::endl; }
      static void SomeFunction(const SomeClass& sc) { std::cout << "const" << std::endl; }
};
class SomeChild : public SomeClass {};
int main(void)
{
   SomeChild sc = SomeChild();
   SomeClass::SomeFunction(sc);
   SomeClass::SomeFunction(SomeChild());
   return 0;
}

一切都很好。

如果没有将临时绑定到引用的更改,这是不可能的。唯一的替代方案是"T","const T&"或通用引用"T&&"(http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers)