【问题标题】:c++ anonymous constructor doing weird thingsC++匿名构造函数做奇怪的事情
【发布时间】:2016-02-02 22:44:30
【问题描述】:

这个示例程序显示了如何调用不同的构造函数,具体取决于您传入的是局部变量、全局变量还是匿名变量。这是怎么回事?

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 构造函数来创建类的匿名实例?谁决定 type(variableName); 应该是定义名为 variableName 的变量的可接受方式?

【问题讨论】:

  • 什么是匿名构造函数?我不知道有这样的事情。
  • Well, that's interesting,为什么puke() 可以在std::string 类上调用。
  • @πάνταῥεῖ,它被 globalStr 在 main 中的声明所掩盖。
  • 这是我所见过的使用{..} 来构造对象而不是(..) 的最佳动机之一。
  • C++(和 C,就此而言)允许您在声明标识符时将括号括起来。声明函数指针时实际上需要这种语法:aClass (*fptr)(std::string)

标签: c++ anonymous default-constructor


【解决方案1】:
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,这与所有其他阴影实例一致。

是否可以通过使用非常量表达式调用其 1-arg 构造函数来创建类的匿名实例?

是的,我能想到四种方法:

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,它返回aClass,带有一个localStr类型的localStrstd::string:

aClass foo(std::string(localStr));

确实,您的问题是由相同的规则造成的 - 如果可以将某些内容解析为有效声明,那么它必须是。这就是为什么aClass(localStr); 是一个声明而不是由一个单独的表达式组成的语句。

【讨论】:

    猜你喜欢
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    • 2015-05-07
    相关资源
    最近更新 更多