C++ вызывающая функция в делегате конструктора
В C++11 конструктор может быть перенаправлен другому конструктору в списке инициализации.
Это нормально для вызова функции в списке инициализации, как в этом вопросе
Также нормально вызывать функцию в делегате конструктора?
Я попробовал код, как это:
#include <iostream>
#include <string>
#include <yaml-cpp/yaml.h>
using namespace std;
YAML::Node ParseFromFile(const string& filepath) {
YAML::Node yaml;
try {
return YAML::LoadFile(filepath);
} catch(const YAML::BadFile& e) {
cout << "error";
}
}
class A {
public:
A(YAML::Node yaml) {
cout << "Got" << endl;
}
A(const string& filepath) : A(ParseFromFile(filepath)) {}
};
int main(int argc, char** argv) {
A a(string(argv[1]));
YAML::Node yaml = ParseFromFile(string(argv[1]));
A b(yaml);
return 0;
}
Для приведенного выше кода, просто передайте ему пустой файл, он напечатает только один "Got" во время инициализации b.
================================================== =====================
Замена строки (argv[1]) на argv [1] заставляет его работать, есть идеи, почему?
1 ответ
Ответ на отредактированный вопрос
Проблема в первой строке в main, она рассматривается как объявление функции, а не как инициализация переменной, фактически, если бы вы скомпилировали ее с помощью clang, она бы предупредила вас об этом:
предупреждение: круглые скобки были устранены как объявление функции
Это связано с тем, что определено в § 6.8 Разрешение неоднозначности в стандарте (AKA Most досадный анализ) (выделено мной...):
В грамматике существует двусмысленность, связанная с выражениями-операторами и объявлениями: выражение-выражение с явным преобразованием типа в стиле функции (5.2.3) в качестве крайнего левого подвыражения может быть неотличимо от объявления, где первый декларатор начинается с ((. В этих случаях заявление является декларацией.
Рассмотрим следующий пример:
#include <iostream>
#include <string>
#include <exception>
using namespace std;
struct A{
string a;
A(string s) : a(s){ cout<< "Ctor" <<endl;}
A(int i) : A(to_string(i)){ }
};
void foo (A (*a)(string*)){
cout<<"yay"<<endl;
}
int main(int argc, char** argv) {
A a1( string(argv[1]) ); // function A a1(std::string*) declaration not a variable
/* ^ ^ ^
| | |
return type name arg type
Same as foo
*/
// foo(a1);// <- compiles but fails only due to linkage
A a2 = A(string(argv[1])); // works
A a3{string(argv[1])}; // works
A a4(string{argv[1]}); // works
A a5( ( string(argv[1]) ) ); // works allso but confusing imho
/* ^ ^
notice extra paren. | |
*/
return 0;
}
Ответ на оригинальный вопрос FWIW
Почему бы просто не попробовать?
Не должно быть никаких проблем, если вы не вызовете функцию, которая будет использовать члены, которые еще не инициализированы.
Например ( демо):
#include <iostream>
#include <string>
using namespace std;
class A {
public:
A(string x) {
cout << "Got " << x << endl;
}
A(int x) : A(std::to_string(x)) {}
};
int main() {
A a(15);
return 0;
}