В этом примере программы показано, как будет вызываться другой конструктор, в зависимости от того, передаете ли вы локальную переменную, глобальную переменную или анонимную переменную. Что здесь происходит?
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-аргументный конструктор с неконстантным выражением? Кто решил что type(variableName);
должен быть приемлемым способом определения переменной с именем variableName
?
aClass(localStr); //this line does not compile
Это пытается объявить переменную типа aClass
названный localStr
, Синтаксис ужасен, я согласен, но сейчас слишком поздно для этого [изменения стандарта].
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.
Это использует globalStr
в main
, что согласуется с любым другим случаем слежки.
Можно ли создать анонимный экземпляр класса, вызвав его 1-аргументный конструктор с неконстантным выражением?
Да, я могу придумать четыре способа:
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
типа std::string
:
aClass foo(std::string(localStr));
На самом деле это то же правило, которое отвечает за ваши проблемы — если что-то может быть проанализировано как правильное объявление, так и должно быть. Поэтому aClass(localStr);
является объявлением, а не утверждением, состоящим из одного выражения.
Других решений пока нет …