#cpp #cpp11 #инициализация
Есть такой класс: class Book { public: char* name; char** authors; int authorsCount; int publishingYear; Book(const char* name_,\ const char* authors[],\ int authorsCount_, \ int publishingYear_); bool operator < (const Book &other) const; void print(void) const; ~Book(); }; Как правильно(и возможно ли вообще) инициализировать объект этого класса используя список инициализации(Braced initialization)? Вот такой вариант почему-то не работает: Book b = {"Skazki", {"Ivanov", "Petrov"}, 2, 1968}; error: could not convert ‘{"Skazki", {"Ivanov", "Petrov"}, 2, 1968}’ from ‘’ to ‘Book’ Book b = {"Skazki", {"Ivanov", "Petrov"}, 2, 1968};
Ответы
Ответ 1
Вы пытаетесь инициализировать указатель const char **authors при помощи инициализатора {"Ivanov", "Petrov"}. Компилятору, разумеется, совершенно не ясно, что вы пытаетесь сделать. Конструировать в такой ситуации временный массив язык не будет. Чтобы в такой ситуации заставить компилятор сконструировать временный объект типа массив из {}-инициализатора, придется явно указать перед ним имя "массивного" типа. При этом "сложные" имена типов в таком контексте неупотребимы, т.е. придется сначала завернуть тип массив в компактное typedef-имя, например так using A = const char *[]; Book b = {"Skazki", A{"Ivanov", "Petrov"}, 2, 1968}; Если бы у вас в конструкторе был параметр типа const char* const (&authors)[2] то компилятор бы самостоятельно расценил ваше {"Ivanov", "Petrov"} как инициализатор для временного массива типа const char *[2]. Но вам этот вариант не подходит, ибо в вашем случае размер массива является значением времени выполнения. Что интересно, GCC не хочет компилировать и вариант с A{"Ivanov", "Petrov"}, ибо не разрешает брать адрес временного массива. Причины такого запрета не ясны. Вроде в стандарте его навскидку не видно. И Clang успешно компилирует этот вариант.Ответ 2
Во-первых следует изменить поля класса чтобы они могли хранить передаваемые таким образом данные. Указатели char * должны быть const char * (или string_view) так как они указывают на неизменяемые массивы со статическим временем жизни полученные из строковых литералов. Указать char * * должен стать контейнером, так как передаваемый массив в любом случае будет временным, а нужно, чтобы он жил на протяжении жизни создаваемого объекта. private: using Authors = ::std::vector; private: char const * m_name; private: Authors m_authors; private: int m_publishingYear; public: explicit Book ( char const * const name , ::std::initializer_list const authors , int const publishingYear ) : m_name{name} , m_authors{authors} , m_publishingYear{publishingYear} {} Book b{"Skazki", {"Ivanov", "Petrov"}, 1968}; Online compiler
Комментариев нет:
Отправить комментарий