Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CPP Set default value for child class

Hello I'm already learning CPP and want to set a default value for child class but I don't know were to set it, I try many things and don't found information on internet. I'm looking for do less constructors ass possible.

I want to set by default the string arm by def0 when no paramters are set

class Parts {
    private:
        std::string _serial;
        bool _functionnal;
    public:
        Parts(std::string &serial, bool functional);
        std::string serial();
};

class Arms : public Parts {
    private:
        std::string _serial = "def0";
    public:
        Arms(std::string &serial, bool functionnal = true) : Parts(serial, functionnal)
        {
        }
};

Parts::Parts(std::string &serial, bool functional)
{
    this->_serial = serial;
    this->_functionnal = functional;
    std::cout << "Name set to: " << serial << std::endl;
}

int main()
{
    std::string sample = "sample";
    Arms Ex(sample, false);
    Arms setAsDefault();

    return 0;
}
like image 319
Benjamin Sx Avatar asked Aug 21 '26 00:08

Benjamin Sx


1 Answers

You already have the basis for using default parameters in place, however you are missing one crucial detail: you need to make the string& a const reference (otherwise you cannot assign it a default value)!

This requires you to change the constructor of Parts (both declaration and definition) to:

Parts(const std::string &serial, bool functional)

And change the Arms class to:

class Arms : public Parts {
    public:
        Arms(const std::string &serial = "def0", bool functionnal = true) : Parts(serial, functionnal)
        {
        }
};

One more detail is that Arms setAsDefault(); does not create a new object, it instead declares a function returning an Arms (this is known as the most vexing parse problem: https://en.wikipedia.org/wiki/Most_vexing_parse)

Instead you need to change it to Arms setAsDefault;

EDIT: In fact you can simplify the constructor of Parts by using member initializer lists, which will also prevent a default string construction (as pointed out by user4581301), e.g.:

Parts::Parts(const std::string &serial, bool functional) : _serial(serial), _functionnal(functional)
{
    std::cout << "Name set to: " << serial << std::endl;
}

So your example changed to do what you wanted is the following code

#include <string>
#include <iostream>

class Parts {
    private:
        std::string _serial;
        bool _functionnal;
    public:
        Parts(const std::string &serial, bool functional);
        std::string serial();
};

class Arms : public Parts {
    public:
        Arms(const std::string &serial = "def0", bool functionnal = true) : Parts(serial, functionnal)
        {
        }
};

Parts::Parts(const std::string &serial, bool functional) : _serial(serial), _functionnal(functional)
{
    std::cout << "Name set to: " << serial << std::endl;
}

int main()
{
    std::string sample = "sample";
    Arms Ex(sample, false);
    Arms setAsDefault;

    return 0;
}

In order to have a constructor that takes only a bool (as asked in the comments) you need to provide another overload for the constructor, e.g. (using C++11 delegating constructors):

Arms(bool functionnal) : Arms("def0", functionnal) {}

EDIT2: As suggested by SergeyA an even better option is to pass the parameters by value and using std::move to move-construct the member variables. In this case your classes look like this:

class Parts {
    private:
        std::string _serial;
        bool _functionnal;
    public:
        Parts(std::string serial, bool functional);
        std::string serial();
};

class Arms : public Parts {
    public:
        Arms(std::string serial = "def0", bool functionnal = true) : Parts(std::move(serial), functionnal)
        {
        }

        Arms(bool functionnal) : Arms("def0", functionnal) {}
};

Parts::Parts(std::string serial, bool functional) : _serial(std::move(serial)), _functionnal(functional)
{
    // Note that `serial` will be empty after the move
    // so you need to access the member variable instead
    std::cout << "Name set to: " << _serial << std::endl; 
}
like image 90
UnholySheep Avatar answered Aug 23 '26 14:08

UnholySheep



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!