Following a tutorial on learncpp.com which discusses declaring member variables outside of constructors. However in previous lessons the author mentions that minimizing the amount of constructors is optimal and can be done by using default values in the parameters of a constructor. This is confusing to me because suddenly there are two places to give default values, directly where you define your member variable, and in the parameter of the constructor. Additionally, it seemed like the whole point of defining default values outside of the constructor was to prevent redundant code because "if you update the default value for a member, you need to touch each constructor".
Here's the example used:
class Ball
{
private:
std::string m_color{ "black" }; //default value "black" declared here
double m_radius{};
public:
Ball(double radius)
: m_radius{ radius } {}
Ball(const std::string& color = "black", double radius = 10.0) //and here!
: m_color{ color },
m_radius{ radius } {}
void print()
{
std::cout << "color: " << m_color << ", radius: " << m_radius << '\n';
}
};
It seems like the solution given by the tutorial uses "black" in two places, contradicting the idea of having all default values in one place to minimize changing constructors. I'm wondering what the best practice here is, and if there is a better way to write this class.
You can rewrite your constructors to not have any default parameters by adding some constructors
std::string m_color{ "black" };
double m_radius{10.}; // specify default value here, exactly like color
public:
Ball() = default; // add a default constructor
Ball(double radius) // keep the constructor taking a double
: m_radius{ radius } {}
Ball(const std::string& color) // add a constructor taking only a string
: m_color{ color } {}
Ball(const std::string& color, double radius) // don't provide defaults for the
: m_color{ color }, // 2 argument constructor
m_radius{ radius } {}
These overloads for the constructor are equivalent to your version, and the defaults are specified only once.