C++:如何将对象传递给另一个对象构造函数?

C++: how to pass an object to another object constructor?

我知道很多人问这个问题,但我来自 Java 并且我已经很长时间没有做过任何 C/C++ 了。

你能提醒我如何在 C++ 中正确地将一个对象传递给另一个对象的构造函数吗?

例如,我需要将一个新的 Light 对象传递给 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 时,对象是通过引用传递还是试图创建一个新对象?

或者我是否需要在 Button 的构造函数中将 Light 声明为指针?

非常感谢任何帮助!

该程序尝试使用默认构造函数启动 ledLight,然后将 l 分配给 ledLight。编译器给你一个错误,因为 Light 没有默认构造函数。试试这个:

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

您缺少默认构造函数。尝试像这样修改您的 class:

class Light {
    int pin;

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

至于为什么你不自动生成默认构造函数,那是因为你已经声明了某种类型的构造函数,所以编译器不会生成默认构造函数(来自 http://en.cppreference.com/w/cpp/language/default_constructor,参见关于隐式 declared/defined 构造函数的部分。


回复评论:

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);

在我看来,你好像在说 "a light named my_led exists" 和 "a button named my_button exists and needs my_led"。您希望按钮指向已存在的特定 LED,还是仅指向具有相同值的 LED?

如果您认为自己想要参考该按钮的实际 LED,那么您可能需要考虑执行以下操作:

class Button {
    const Light *ledLight;

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

这样,您的 Button 就有一个指向您创建的 Light 的指针,无论您对 Button 代码中的 Light 做什么,都将在您已经实例化的 Light 对象,而不是您通过使用当前 Button 构造函数复制构造 Light 创建的 Light 的一些单独副本。

如果您想让按钮实际修改灯光,请像这样修改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 有一根不变的电线。如果您认为您将重新分配从按钮点亮的 LED,您也可以从 Button 中的指针成员中取出 const 关键字。