Построение дочернего класса с добавленной переменной-членом - PullRequest
0 голосов
/ 27 июня 2018

В моей программе есть абстрактный класс, от которого наследуются несколько классов. Каждый дочерний класс представляет переменную-член для хранения данных. Я заметил, что при попытке инициализировать дочерний класс, используя агрегатную инициализацию или список инициализаторов, я получаю ошибки, показанные ниже.

struct FooBase {};
struct Foo : FooBase { int value; };

int main()
{
    Foo f = {8}; // "initializer for aggregate with no elements requires explicit braces"
    Foo f{8};    // same error as above
}

Я подумал, что это потому, что Foo наследует конструкторы от FooBase, но у меня есть пара вопросов о поведении.

  • Поскольку тип указывается во время компиляции, почему агрегатный конструктор Foo не имеет приоритета?
  • Есть ли способ принудительно установить приоритет конструктора по умолчанию, чтобы возможна вышеуказанная инициализация?
  • (немного шире) Как вообще (стандартные и агрегатные) конструкторы классов передаются их дочерним элементам?

Как я понимаю, опциями будет установка данных после инициализации (или создание метода установки) или явное определение конструктора для Foo. Однако, в частности, в контексте последнего вопроса, что происходит с конструкторами перемещения и копирования? (Есть ли хорошая практика для обеспечения хорошего поведения классов при наследовании?)

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Конструктор по умолчанию - это конструктор, который не принимает аргументов, а value инициализирует всех членов класса; конструктор, который принимает int и использует его для инициализации value, должен быть определяемым пользователем конструктором.

Конструкторы не передаются своим детям. Если вы добавите , используя объявление using FooBase::FooBase в определении Foo, тогда все конструкторы FooBase станут видимыми в Foo (хотя в этом примере это не будет иметь эффекта, поскольку FooBase содержит только конструкторы, предоставленные по умолчанию).

0 голосов
/ 27 июня 2018

В вашем примере вам нужно предоставить дополнительные пустые скобки для инициализации базового класса:

Foo f = {{}, 8};
Foo f{{}, 8};

Вообще говоря, не каждый класс может быть агрегированно инициализирован. Класс считается совокупным, если он имеет (см. source ):

  • нет личных или защищенных нестатических элементов данных
  • нет пользовательских, унаследованных или явных конструкторов (допускаются явно заданные по умолчанию или удаленные конструкторы)
  • нет виртуальных, частных или защищенных базовых классов
  • нет виртуальных функций-членов

Кроме того, не существует такого понятия, как «конструктор агрегатов», и конструктор по умолчанию никак не связан с инициализацией агрегатов.

Конструкторы базовых классов не наследуются , если вы не используете using Base::Base для этого. Конструкторы копирования и перемещения также не наследуются . Они автоматически генерируются компилятором для каждого класса, если они явно не определены или неявно удалены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...