Построение объекта внутри объекта - PullRequest
3 голосов
/ 23 апреля 2019

У меня есть объект A, объявленный внутри класса, я хочу инициализировать объект A при инициализации объекта B:

class A{
    private:
        int num1;
        string word;
    public:
        A(int,word);
};

A::A(int _num1, string _word){
    num1 = num1;
    word = _word;
}

class B{
    private:
        char letter;
        A a;
    public:
        B(char,int,string)
};

B::B(char _letter, int _num1, string _word){
    letter = _letter;
    a(_num1, _word);
}

Это дает ошибку: может быть вызвана только функция. У меня вопрос: как я могу иметь объект внутри другого объекта, который может быть инициализирован конструктором внешних объектов.

Ответы [ 2 ]

5 голосов
/ 23 апреля 2019

Вы должны инициализировать элемент данных a с помощью списка инициализаторов элементов ,

B::B(char _letter, int _num1, string _word) : a(_num1, _word) {
    letter = _letter;
}

или лучше

B::B(char _letter, int _num1, string _word) : letter(_letter), a(_num1, _word) {}

Обратите внимание, что при попадании в тело конструктора B, a должно быть инициализировано. Без использования списка инициализаторов членов, как указано выше, a будет пытаться инициализироваться с помощью конструктора по умолчанию, но A не имеет его. И a(_num1, _word); просто пытается вызвать a, как будто это функтор, но a нет.

4 голосов
/ 23 апреля 2019

Списки инициализаторов предназначены только для этой цели.Они используются для вызова конструктора членов, а не для их назначения.Это может быть немного быстрее, если построение по умолчанию и последующее назначение выполняются медленнее, чем создание напрямую.Они должны использоваться вместо назначения почти во всех случаях.Использование их для инициализации примитивов не дает никакого преимущества в производительности (в данном случае это просто вопрос стиля, поэтому я обычно делаю это в любом случае).

Так вы бы написали свой конструктор, используя списки инициализаторов членов.

B::B(char _letter, int _num1, string _word)
    : letter(_letter), a(_num1, _word) {}

Это можно немного улучшить.Мы можем дать параметрам те же имена, что и членам.В этом случае компилятор сделает «правильную вещь» и инициализирует член параметром.Это также позволяет избежать запуска идентификаторов с подчеркиванием , что является отдельной проблемой .

B::B(char letter, int num1, string word)
    : letter(letter), a(num1, word) {}

Одна вещь, которую следует отметить в списках инициализаторов элементов, - это порядок инициализации.Члены будут инициализированы в том порядке, в котором они объявлены в классе.В этом случае letter будет инициализирован до a. Порядок списков инициализации не влияет на порядок инициализации. Рассмотрим этот пример:

B::B(char letter, int num1, string word)
    : a(num1, word), letter(letter) {}

Это инициализирует letter, а затем a.Вот почему вы должны убедиться, что порядок совпадает с объявленным в классе.Если вы передадите соответствующие флаги предупреждения своему компилятору, он сообщит вам об этом, и ваша IDE может даже изменить порядок вещей для вас.

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