为什么在传递给参数时不能隐式构造给定合适构造函数的对象?
Why can't I implicitly construct an object given a suitable constructor when passing to an argument?
在下面的示例中,为什么我不能简单地将string
传递给printFoo()
?
#include <string>
#include <iostream>
using namespace std;
class Foo {
public:
Foo(const Foo &foo) : str(foo.str) {}
Foo(string str) : str(str) {}
string str;
};
void printFoo(Foo foo) {
cout << foo.str << endl;
}
int main() {
Foo foo("qux");
printFoo(foo); // OK
printFoo("qix"); // error: no matching function for call to 'printFoo'
return 0;
}
无论出于何种原因,我脑海中都有一个构造函数会自动确定并使用,以便构造一个对象。
为什么我不能这样做,但我可以将一个char[n]
常量传递给接受std::string
的参数,例如?
将涉及两个隐式转换:
- 到
std::string
- 到
Foo
C++最多执行一个:
从 4 标准转换 (N3337)
标准转换是具有内置含义的隐式转换。 第4条列举了此类转换的全部集合。一个标准 转换序列是标准转换序列 以下顺序:
— 以下集合中的零个或一个转换: 左值到重值转换、数组到指针转换以及 函数到指针的转换。
— 零或一次转换从 以下集合:积分促销、浮点促销、积分 转换、浮点转换、浮点积分 转换、指针转换、指向成员的指针转换,以及 布尔转换。
— 零或一次资格转换。
还有 12.3 转换 (N3337)
1 类对象的类型转换可以由构造函数和 通过转换函数。这些转换称为用户定义 转换,用于隐式类型转换(条款 4),用于 初始化 (8.5) 和显式类型转换 (5.4、5.2.9)。
2 用户定义的转换仅在明确的情况下应用 (10.2, 12.3.2).转换遵守访问控制规则(第 11 条)。 访问控制在歧义解决 (3.4) 之后应用。
[...]
4 最多一个用户定义隐式应用转换(构造函数或转换函数)到单个值。
(强调我的)
根据C++标准 §12.3/4 转换 [class.conv]:
最多一个用户定义的转换(构造函数或转换) 函数)隐式应用于单个值。
因此,不允许编译器连续应用两个转换。也就是说,首先从const char[4]
到std::string
,其次从std::string
到Foo
.
为此,您需要定义一个额外的构造函数:
Foo(char const *str_) : str(str_) {}
这是因为编译器可以考虑一次转换。
要执行您需要执行的操作,编译器需要植入两个转换。
printFoo("qix");
// Actually needs.
printFoo(Foo(std::string("qix")));
如果您更改此设置以传递字符串,它将起作用。
printFoo(std::string("qix"));
这一切背后的主要原因是字符串文字的类型char const[<size>]
不std::string
正如其他人所提到的,问题是需要 2 次转换。您可以使用s
文本将字符串文本转换为实际std::string
printFoo("qix"s);
演示
- 对象实例化调用构造函数的次数太多
- Arduino C++在构造函数中用参数声明对象数组
- 模板,函数使用错误的构造函数来复制我的对象
- 我使用向量来创建类对象列表.初始化向量时如何使用参数调用构造函数?
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 通过构造函数创建的所有对象都具有相同的向量
- 是什么让放置新调用对象的构造函数?
- 复制包含C++所有元素的对象!(构造函数和赋值,最佳实践?
- C++ 对象指针数组的复制构造函数
- 在构造函数中输入对象时C++类成员作用域
- C++:将初始化的对象传递给另一个类的构造函数;需要不必要的构造函数吗?
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 如何从构造函数副本 T(const T&)调用对象 T?
- 将另一个类的对象传递到当前类C++的构造函数中(不是成员初始化)
- 如何将我编写的对象传递到另一个类的构造函数中?
- 使用向量初始化参数化构造函数的对象数组
- 在C++中将对象从另一个类传递到另一个类的构造函数?
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- 构造函数对象赋值是否泄漏内存
- gcc中不可移动构造函数对象的std::函数