简体   繁体   中英

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

I know this question is asked a lot, but I come from Java and I haven't done any C/C++ for a very long time.

Can you please remind me how to correctly pass an object to another object's constructor in C++?

For example, I need to pass a new Light object to the Button constructor:

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

This is how I would do it in a Java-like fasion. However this produces the following error:

::  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

Is the object being passed by reference or is it attempting to create a new one when I create a new Button?

Or do I need to declare the Light as a pointer in the Button's constructor?

Any help is much apreciated!

The program tries to initiate ledLight using the default constructor and then assigns l to ledLight . The compiler gives you an error because there is no default constructor for Light . Try this instead:

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

You're missing a default constructor. Try modifying your class like this:

class Light {
    int pin;

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

As to why you're not automatically generating a default constructor, it's because you're already declaring a constructor of some type, so the compiler won't generate a default one (from http://en.cppreference.com/w/cpp/language/default_constructor , see sections on implicitly declared/defined constructors).


In response to the comment:

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

When your executing code gets to the last line:

Button my_button(my_led);

You're instantiating a Button and a Light as part of the Button instantiation process. Without specifying a default Light::Light() constructor, you're leaving out instructions on how to instantiate a Light object without a value, which you need to do before copying the value of my_led into my_button. You'll get the results you intended, you're just currently leaving out instructions to the compiler on how to perform an intermediate step, ie instantiate Light without any arguments.


Some things to think about:

What are you really trying to do? Just by looking at your instruction code:

Light my_led(0);

Button my_button(my_led);

It seems to me like you're trying to say "a light named my_led exists" and "a button named my_button exists and needs my_led ". Do you want the button to refer to a specific LED that exists already, or just an LED that has the same values?

If you think you'll want to refer to the actual LED from that button then you might want to consider doing the following:

class Button {
    const Light *ledLight;

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

That way, your Button has a pointer to the Light you created, and whatever you do with the Light inside your Button code will be performed on the Light object you already instantiated, instead of some separate copy of Light you create by copy-constructing Light with your current Button constructor.

If you want the button to actually modify the light, revise Button like so:

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}
        {}
};

The above you could think of as having an unchanging wire from the button to the LED. If you think you'll be reassigning the LED that gets lit from the button, you'd take out the const keyword from the pointer member in Button as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM