2015-08-01 4 views
0

Я знаю, что этот вопрос задан очень много, но я пришел из Java, и я не делал никаких C/C++ в течение очень долгого времени.C++: как передать объект другому конструктору объекта?

Не могли бы вы напомнить мне, как правильно передать объект другому конструктору объекта в C++?

Например, мне нужно, чтобы передать новый свет объекта в конструкторе Button:

// LED Light 
class Light { 
    int pin; 

    public: 
     Light(int p) { 
      pin = p; 
     } 
}; 

// BUTTON 
class Button { 
    Light ledLight; 

    public: 
     Button(Light l) { 
      ledLight = l; 
     } 

}; 

Light my_led(0); 

Button my_button(my_led); 

Это, как я хотел бы сделать это в Java-как фьюжн. Однако это приводит следующее сообщение об ошибке:

:: In constructor ‘Button::Button(Light)’: 
:: 16:19: error: no matching function for call to ‘Light::Light()’ 
:: 16:19: note: candidates are: 
:: 6:3: note: Light::Light(int) 
:: 6:3: note: candidate expects 1 argument, 0 provided 
:: 2:7: note: Light::Light(const Light&) 
:: 2:7: note: candidate expects 1 argument, 0 provided 

ли объект, передаваемый по ссылке или он пытается создать новую, когда я создаю новую кнопку?

Или мне нужно объявить свет как указатель в конструкторе Button?

Любая помощь очень высоко ценится!

+0

Теперь напишите 100 раз: «C is ** not ** C++ is ** not ** C!» – Olaf

+0

Также стоит отметить, что в отличие от Java изменения, внесенные в 'my_button.ledLight', не изменят содержимое' my_led'. Вы скопировали объект. –

+0

@ Олаф, мне очень жаль и особенно стыдно, потому что я сам часто прошу людей сделать то же самое с «Java/JavaScript». Спасибо за редактирование. @BillLynch, как я могу передать 'my_led' прямо в' my_button'? Так что изменения от кнопки влияют на ее содержимое. – YemSalat

ответ

2

Вам не нужен конструктор по умолчанию. Попробуйте изменить свой класс, как это:

class Light { 
    int pin; 

    public: 
     Light()=default; //<-- put this in 
     Light(int p) { 
      pin = p; 
     } 
}; 

Относительно того, почему вы не автоматически генерировать конструктор по умолчанию, это потому, что вы уже объявить конструктор некоторого типа, так что компилятор не будет генерировать по умолчанию один в (от http://en.cppreference.com/w/cpp/language/default_constructor, см. разделы о неявно объявленных/определенных конструкторах).


В ответ на комментарий:

Wouldn't it attempt to call the default constructor instead of the one which passes the arguments?

Когда выполнение кода дойдет до последней строки:

Button my_button(my_led); 

Вы инстанцировании ButtonLight и как часть Button процесс создания экземпляра. Не указывая конструктор по умолчанию Light::Light(), вы оставляете инструкции о том, как создать экземпляр объекта Light без значения, которое необходимо выполнить перед копированием значения my_led в my_button. Вы получите результаты, которые вы намеревались, в настоящее время вы оставляете инструкции для компилятора о том, как выполнить промежуточный шаг, то есть создать экземпляр Light без каких-либо аргументов.


Некоторые вещи, чтобы думать:

Что вы действительно пытается сделать?Просто глядя на ваш код инструкции:

Light my_led(0); 

Button my_button(my_led); 

Мне кажется, что вы пытаетесь сказать, «свет по имени my_led существует» и «кнопка под названием my_button существует и нуждается в my_led». Вы хотите, чтобы кнопка ссылалась на определенный светодиод, который уже существует, или только светодиод, который имеет одинаковые значения?

Если вы думаете, вы хотите сослаться на фактический LED от этой кнопки, то вы можете рассмотреть возможность сделать следующее:

class Button { 
    const Light *ledLight; 

    public: 
     Button(const Light& l) : 
      ledLight{&l} 
     {} 
}; 

Таким образом, ваш Button имеет указатель на Light вы создали , и все, что вы делаете с Light внутри вашего кода Button, будет выполнено на объекте Light, который вы уже создали, вместо отдельной копии Light, которую вы создаете путем копирования-построения Light с вашим текущим конструктором Button.

Если вы хотите, чтобы кнопка на самом деле изменить свет, пересмотреть Button так:

class Button { 
    // constant reference to changeable object 
    Light * const ledLight; 

    public: 
     /** 
     * You're providing a reference to a light that can be changed 
     * (i.e. button code can toggle lit status or something) 
     */ 
     Button(Light & l) : 
      ledLight{&l} 
     {} 
}; 

выше вы могли бы думать, как имеющие неизменный провод от кнопки на LED. Если вы думаете, что будете переназначать светодиод, который горит от кнопки, вы также вытащите ключевое слово const из элемента указателя в Button.

+0

Не попытается ли он вызвать конструктор по умолчанию вместо того, который передает аргументы? – YemSalat

+1

Если вы явно определяете конструктор, по умолчанию он не будет создан автоматически –

+0

@YemSalat Когда вы делаете 'Button my_button (my_led);', вы уже вызываете конструктор 'Light :: Light()' по умолчанию для первого экземпляра член 'Light' при создании кнопки' Button'. Затем вы копируете значение 'Light', указанное в конструкторе' Button :: Button (Light) '. – Teeeeeeeeeeeeeeeeeeeeeeeeeeeej

7

Программа пытается инициировать ledLight с использованием конструктора по умолчанию, а затем назначает l - ledLight. Компилятор выдает сообщение об ошибке, потому что нет конструктора по умолчанию для Light. Попробуйте это вместо:

Button(Light l): ledLight(l) { } 
+0

Спасибо! Но каков правильный синтаксис, если у меня есть больше параметров, например: 'Button (int pin, long time, Light l)'? – YemSalat

+0

@YemSalat Вы можете попробовать 'Button (int pin, long time, Light l): b_pin (pin), b_time (time), ledLight (l) {}' – yizzlez

+0

Кроме того, помните, когда вы строите объекты таким образом, они будут уничтоженный в конце блока (функция, цикл, if-clause, что угодно). Если вы ожидаете, что ваш объект Light будет жить дольше, вы должны использовать 'new Light (0)' и передать его как указатель на Button (предпочтительно общий указатель). –