2016-10-19 10 views
-1

Предположим, что у меня есть класс следующим образом:Конструкторы с объектами в качестве параметров

class A{ 
    int x ; 
    A(int i){ 
     x = i ; 
    } 
} 

И у меня есть еще один класс B, который имеет экземпляр класса А в качестве объекта члена.

class B{ 
    int y ; 
    A obj_a ; 
    B(int j , A a){ 
     y = j ; 
     obj_a = a ; 
    } 
} 

Когда я делаю следующее:

int main(){ 
     A obj1(1) ; // obj.x has value 1 
     B obj2(2 , obj1) ; 
    } 

2-я строка выдает ошибку ничего не говоря, вызов функции вида A :: A(). Я знаю, это означает, что конструктор стиля по умолчанию отсутствует, но зачем мне это нужно? obj1 создается с использованием определенного конструктора, так что это не проблема.

Моя текущая мысль состоит в том, что A a и obj_a = a будут ссылаться на конструктор копирования, который неявно определен.

Примечание: Для краткости я исключил частную, общественную и т. Д.

+1

Сообщение фактическая ошибка. Ваш ctor, вероятно, жалуется, что это должно быть 'const int i'; – stark

+1

Вы явно просили об этом, не используя список инициализаторов. – kfsone

ответ

1

Объект должен быть полностью последовательным, все ее члены построили, к тому времени, он входит в тело конструктора. Таким образом, в

B(int j , A a){ 
    y = j ; 
    obj_a = a ; 
} 

перед тем

{ 
    y = j ; 
    obj_a = a ; 
} 

получает шанс сделать что-нибудь, obj_a должно быть построено.

Поскольку никаких инструкций о том, как построить obj_a представлено не было с Member Initializer List, obj_a будет построен с помощью конструктора по умолчанию для класса A. Класс A не имеет конструктора по умолчанию, не A::A(), поэтому ошибка возникает.

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

Класс B должен быть:

class B{ 
    int y ; 
    A obj_a ; 
    B(int j , A a): y(j), obj_a(a) 
    { 
    } 
} 
+0

- это объект 'a', созданный по значению здесь? Можно ли пройти по ссылке? –

+0

@AbhinavVishak 'a' в настоящее время передается по значению и, возможно, требует копии. Да, вы можете передать 'a' по ссылке. – user4581301

3

obj_a = a вызывает operator=, а не конструктор копирования. Дело в том, что obj_a инициализируется с использованием конструктора по умолчанию, , потому что вы не указали, какой конструктор вызывать в списке инициализаторов.

B(int j , A a) /*: obj_a{}*/ { /*...*/ } 
       ^^^^^^^^^^^^^ 
      implicit call to default constructor 

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

B(int j , A a) : obj_a{ a } { /*...*/ } 
+0

Ну, дело не столько в 'obj_a = a'. Его 'A a' внутри списка параметров. Как это исправить? –

+1

@AbhinavVishak 'A a' ** не ** проблема, когда она находится в списке параметров. Проблема заключается в отсутствии 'obj_a' в списке mem-initialiser (список, следующий за': '). – Angew

+0

@agnew Я сделал изменения, которые вы предложили, и он компилируется. Благодаря ! Я все еще немного запутался в использовании списков инициализаторов, но немного почитаю об этом. Я предполагаю, что после использования ': obj_a {a}', мне не понадобится 'obj_a = a' ?? –

 Смежные вопросы

  • Нет связанных вопросов^_^