c ++匿名构造函数做奇怪的事情
c++ anonymous constructor doing weird things
此示例程序展示了如何根据您传入的是局部变量、全局变量还是匿名变量来调用不同的构造函数。这是怎么回事?
std::string globalStr;
class aClass{
public:
aClass(std::string s){
std::cout << "1-arg constructor" << std::endl;
}
aClass(){
std::cout << "default constructor" << std::endl;
}
void puke(){
std::cout << "puke" << std::endl;
}
};
int main(int argc, char ** argv){
std::string localStr;
//aClass(localStr); //this line does not compile
aClass(globalStr); //prints "default constructor"
aClass(""); //prints "1-arg constructor"
aClass(std::string("")); //also prints "1-arg constructor"
globalStr.puke(); //compiles, even though std::string cant puke.
}
鉴于我可以调用 globalStr.puke()
,我猜测通过调用 aClass(globalStr);
,它正在创建一个名为 globalStr
且类型为 aClass
的局部变量,即正在使用而不是全局 globalStr
。调用 aClass(localStr);
试图做同样的事情,但编译失败,因为 localStr
已经声明为 std::string
。是否可以通过使用非常量表达式调用其 1-arg 构造函数来创建 class 的匿名实例?谁决定 type(variableName);
应该是定义名为 variableName
的变量的可接受方式?
aClass(localStr); //this line does not compile
这试图声明一个名为 localStr
的类型 aClass
的变量。语法很糟糕,我同意,但现在 [改变标准] 已经太晚了。
aClass(globalStr); //prints "default constructor"
这声明了一个名为 globalStr
。这个 globalStr
变量隐藏了全局变量。
aClass(""); //prints "1-arg constructor"
这将创建类型为 aClass
的临时对象。
aClass(std::string("")); //also prints "1-arg constructor"
这也会创建一个临时文件。
globalStr.puke(); //compiles, even though std::string cant puke.
这使用 main
中的 globalStr
,这与所有其他阴影实例一致。
Is it possible to create an anonymous instance of a class by calling its 1-arg constructor with a non-constant expression?
是的,我可以想到四种方法:
aClass{localStr}; // C++11 list-initialization, often called "uniform initialization"
(void)aClass(localStr); // The regular "discard this result" syntax from C.
void(aClass(localStr)); // Another way of writing the second line with C++.
(aClass(localStr)); // The parentheses prevent this from being a valid declaration.
作为旁注,这种语法通常是最令人烦恼的解析的原因。例如,下面声明了一个函数 foo
returns aClass
,其中一个参数 localStr
类型为 std::string
:
aClass foo(std::string(localStr));
事实上,这是导致您的问题的相同规则 - 如果某些内容可以被解析为有效声明,那么它一定是。这就是为什么 aClass(localStr);
是一个声明而不是由一个单独的表达式组成的语句。
此示例程序展示了如何根据您传入的是局部变量、全局变量还是匿名变量来调用不同的构造函数。这是怎么回事?
std::string globalStr;
class aClass{
public:
aClass(std::string s){
std::cout << "1-arg constructor" << std::endl;
}
aClass(){
std::cout << "default constructor" << std::endl;
}
void puke(){
std::cout << "puke" << std::endl;
}
};
int main(int argc, char ** argv){
std::string localStr;
//aClass(localStr); //this line does not compile
aClass(globalStr); //prints "default constructor"
aClass(""); //prints "1-arg constructor"
aClass(std::string("")); //also prints "1-arg constructor"
globalStr.puke(); //compiles, even though std::string cant puke.
}
鉴于我可以调用 globalStr.puke()
,我猜测通过调用 aClass(globalStr);
,它正在创建一个名为 globalStr
且类型为 aClass
的局部变量,即正在使用而不是全局 globalStr
。调用 aClass(localStr);
试图做同样的事情,但编译失败,因为 localStr
已经声明为 std::string
。是否可以通过使用非常量表达式调用其 1-arg 构造函数来创建 class 的匿名实例?谁决定 type(variableName);
应该是定义名为 variableName
的变量的可接受方式?
aClass(localStr); //this line does not compile
这试图声明一个名为 localStr
的类型 aClass
的变量。语法很糟糕,我同意,但现在 [改变标准] 已经太晚了。
aClass(globalStr); //prints "default constructor"
这声明了一个名为 globalStr
。这个 globalStr
变量隐藏了全局变量。
aClass(""); //prints "1-arg constructor"
这将创建类型为 aClass
的临时对象。
aClass(std::string("")); //also prints "1-arg constructor"
这也会创建一个临时文件。
globalStr.puke(); //compiles, even though std::string cant puke.
这使用 main
中的 globalStr
,这与所有其他阴影实例一致。
Is it possible to create an anonymous instance of a class by calling its 1-arg constructor with a non-constant expression?
是的,我可以想到四种方法:
aClass{localStr}; // C++11 list-initialization, often called "uniform initialization"
(void)aClass(localStr); // The regular "discard this result" syntax from C.
void(aClass(localStr)); // Another way of writing the second line with C++.
(aClass(localStr)); // The parentheses prevent this from being a valid declaration.
作为旁注,这种语法通常是最令人烦恼的解析的原因。例如,下面声明了一个函数 foo
returns aClass
,其中一个参数 localStr
类型为 std::string
:
aClass foo(std::string(localStr));
事实上,这是导致您的问题的相同规则 - 如果某些内容可以被解析为有效声明,那么它一定是。这就是为什么 aClass(localStr);
是一个声明而不是由一个单独的表达式组成的语句。