请考虑以下内容:
class Foo {
public:
Foo (const char *in) {
printf ("C string constructor called\n");
}
Foo (std::string const &in) : Foo(in.c_str()) {
printf ("C++ string constructor called\n");
}
};
Foo bar ("I never asked for this");
//C string constructor called
因此,常量string
被视为const char *
。
但是,如果我们将std::string
构造函数设为“ primary”,会发生什么变化?
我们可以期望在不调用与C字符串相关的对象的情况下创建std::string
对象并将其传递给相应的构造函数吗?
class Foo {
public:
Foo (std::string const &in) {
printf ("C++ string constructor called\n");
}
Foo (const char *in) : Foo(std::string (in)) {
printf ("C string constructor called\n");
}
};
Foo bar ("I never asked for this");
//C++ string constructor called
//C string constructor called
同样,C字符串构造函数被称为 first 。
此行为是在C ++标准中描述的还是与编译器相关的?
对于例如模板还是重载函数?
我使用GCC 7.3.0(MSYS2 x64)进行了编译。
答案 0 :(得分:3)
"I never asked for this"
是string literal,由const char
元素组成:
Foo bar ("I never asked for this"); // calls Foo (const char *in)
因此,Foo (const char *in)
将始终通过重载决议被选择,无论您声明构造函数的“顺序”如何。
如您第二个示例所示,
Foo (const char *in) : Foo(std::string (in))
delegating constructor被选中,并将调用初始化构造列表中唯一成员选择的目标构造函数。
答案 1 :(得分:2)
在C ++中没有 primary 构造函数。
您观察到的是,首先执行了委托给构造函数(目标构造函数)的主体。然后是委托的构造函数的主体(委托构造函数)。
在这种情况下,目标构造函数由重载解析选择并首先执行,然后控件返回到委托构造函数并执行其主体。
答案 2 :(得分:1)
Overload Resolution和Constructor Delegation是完全互不影响的两个完全不同的事物。
重载解决方案在可能的情况下避免了隐式转换。
像"I never asked for this"
这样的字符串文字是const char[]
,它衰减为const char *
。这与您的const char *
构造函数完全匹配,因此被调用。用字符串文字作为输入来调用std::string
构造函数将需要进行隐式转换,因为编译器将构造一个临时的std::string
对象以绑定到std::string const &
引用。
您改写了以下代码:
Foo bar (std::string("I never asked for this"));
或者这个:
std::string str = "I never asked for this";
Foo bar (str);
然后将调用std::string const &
构造函数而不是const char *
构造函数,因为没有从std::string
到const char *
的隐式转换。
构造函数如何相互委托是一个实现细节,在编译器确定要调用哪个 构造函数之后。