Is it possible to have 1 constructor have the option of being a default constructor if a parameter is not passed in.
Example, instead of having 2 constructors, where 1 is the default constructor and another is a constructor that initializes numbers passed in, is it possible to only have 1 constructor that if a value is passed in, set that value to a member function, and if no value is passed in, set the member function to a number.
example:
WEIGHT.H file:
class Weight
{
public:
Weight() { size = 0; }
Weight(int a) : size(a) {}
int size;
};
MAIN.CPP file:
int main(void)
{
Weight w1;
Weight w2(100);
}
I've been working on different school projects and they all require to have different types of constructors, and i'm wondering if there is a way to only have it once so it saves time.
Thanks for the help.
Yes, a constructor parameter may have a default argument, just like other functions can. If all of the parameters of a constructor have default arguments, the constructor is also a default constructor. So, for example,
class Weight
{
public:
explicit Weight(int a = 0) : size(a) { }
int size;
};
This constructor may be called with a single argument or with no arguments; if it is called with no arguments, 0 is used as the argument for the a parameter.
Note that I've also declared this constructor explicit. If you have a constructor that may be called with a single argument, you should always declare it explicit to prevent unwanted implicit conversions from occurring unless you really want the constructor to be a converting constructor.
(If you aren't familiar yet with converting constructors or implicit conversions, that's okay; just following this rule is sufficient for most of the code you'll ever write.)
Yes its possible as suggested by James but as you know if you are not defining the Default constructor the compiler would take over the definition part if you have not provided any constructor definition.
Its not an issue as such but its a better practice to define the Default constructor for proper initialization of values.
Google C++ Style guide also recommends it.
Related
I read a few different topics on these forums and I'm not getting a clear answer on it.
I have two questions, what is the difference between a default/base construct and a construct initialize list? They look the same to me, here are my examples. Do I have them commented correctly as well as what they are?
//In my .h file:
class Complex {
public:
Complex();
Complex(double, double);
private:
double real;
double imag;
};
//In my implementation file:
Complex::Complex() :real(NULL), imag(NULL) // initialization list
{
}
Complex::Complex(double inReal, double inImag) // default constructor
{
real = inReal;
imag = inImag;
}
I have two questions, what is the difference between a default/base construct and a construct initialize list?
A default constructor is a constructor that will be invoked when you create an object but don't specify any constructor arguments. For example, all these variables will be initialised by a call to the default constructor:
Complex myComplex1;
Complex myComplex2();
Complex myComplex3{};
Some other constructors do require arguments, so they're not default constructors.
In the implementation of any constructor (whether a default constructor or not) for an object with bases or member variables or constants, you can use an initialisation list to construct/initialise those bases or members.
They look the same to me, here are my examples. Do I have them commented correctly as well as what they are?
You didn't have them commented correctly. A fixed version is:
Complex::Complex() // default constructor as it does not require args
: real{}, imag{} // initialization list: sets both to 0.0
{ }
Complex::Complex(double inReal, double inImag) // NOT a default constructor
// as it requires arguments
: real(inReal), imag(inImag) // initialisation list
{
// real = inReal; // set in the initialisation list instead
// imag = inImag;
}
The non-default constructor above is invoked when you create an object while specifying matching constructor arguments:
Complex myComplex4(3.1, 2);
Complex myComplex5{-2.3, 2.7};
It's a good idea to preferentially use an initialisation list to construct your bases and set your members: otherwise at best they'll be default initialised then assigned to, which can be less efficient, but for references and constants you simply have to use an initialisation list.
It is possible to create a default constructor with arguments with default values:
Complex(double inReal = 0.0, double inImag = 0.0)
: real(inReal), imag(inImag)
{ }
This single constructor can reasonably replace both the constructors in your code.
In this case,
Complex::Complex() : real(NULL), imag(NULL)
{
}
would be your default constructor, because it is the one here that has no parameters.
An initializer list is what you see following your default constructor's name, being
:real(NULL), imag(NULL)
This is a list of member initializations that take place upon calling the default constructor Complex::Complex()
As an aside, NULL is a value meant to represent a pointer that does not point to any valid addressable memory location. It's not exactly applicable to double types.
I understood 'explicit' concept related to constructors in C++ which will take single parameter as input. But I read on some websites that we need to change the constructor to explicit, irrespective of the number of parameters the constructor will take as input.
Can any one please help me to understand below issues.
Why do we need to make a constructor as explicit if it doesn't take any input?
What is the use of making a constructor as explicit if it takes more than one parameter and all the parameters are not default?
Why do we need to make a constructor as explicit if it doesn't take any input?
That seems incorrect to me. A constructor needs to be explicit if you don't want the constructor to be called automatically.
Say you have:
struct Foo
{
Foo() {}
Foo(int) {}
};
void bar(Foo)
{
}
Then,
bar(1);
will work. It is translated as:
bar(Foo(1));
If there is a default constructor, i.e. one that does not take any arguments, there is nothing to convert from. You may not use:
bar();
and hope to get it translated as:
bar(Foo{});
What is the use of making a constructor as explicit if it takes more than one parameter and all the parameters are not default?
This one has some validity.
If you had:
struct Foo
{
Foo() {}
Foo(int, int) {}
};
void bar(Foo)
{
}
You may not use
bar(10, 20);
or
bar((10, 20));
and hope to have it translated as:
bar(Foo(10, 20));
However, you may use:
bar({10, 20});
and it will be translated as:
bar(Foo{10, 20});
If you want to prevent use of this syntax, bar({10, 20}), you may make the constructor explicit. IMO, this has less utility. The potential for inadvertently misusing a constructor with one argument is real. The potential for inadvertently misusing a constructor with more than one argument is very small.
Just to complement #R Sahu's answer from a different perspective:
The recommendation to use explicit for every constructor irrespective of how many arguments it takes can steam from the fact that strictly speaking every C++ constructor should be explicit by default and instead we would use implicit keyword: why constructors aren't explicit by default?
I saw this problem so many times: initially a class has a default constructor. Then after a while it's modified and a parameter is added. It's very easy to forget to add explicit in this case.
It's even easier to forget to add explicit when you remove a parameter from a two-arguments constructor. Also often your initial explicit one-parameter constructor got additional parameters or lost its parameter but explicit was left by mistake and compiler doesn't complain about this.
After a while your code starts to look like a christmas tree with many constructors that should be explicit but are not and others that are but shouldn't.
I suppose it's the reason why the website you mentioned recommends to use explicit always.
class Act {
protected:
string Owner;
double Balance;
public:
explicit Act(int = 0);
double getBalance() { return Balance; };
};
What is the meaning of line of constructor Act(int =0); Need what int=0 would do here.
Explanation
explicit Act (int = 0);
defines a constructor, that construct an Act from an int parameter. The =0 means that if the parameter can be omitted, it will have a default value of 0. The explicit keyword tells the compiler not to use this constructor for making an implicit conversion.
Examples of use
As it is:
Act a1; // Will generate the same code as Act a1(0);
Act a5{}; // Same as above, but using the braced initialization
Act a2(12); // Obvious
Act a3=13; // Ouch ! Compiler error because of explicit
Act a4 = Act(13); // Ok, because now the call is explicit
If you wouldn't have the explicit keyword, then this line would be ok
Act a3=13; // If not explicit, this is the same than Act a3=Act(13);
Important remarks
The default value is not something that is part of the constructor itself, but a behavior that is defined on the caller side, based on the declaration of the constructor known by the caller.
This means that you could include declare the class with different default values in different compilation units. Although strange, this is perfectly valid.
Note that the absence of parameter name in the declaration is not a problem either, because, the parameter name can be declared within the constructor definition:
Act::Act(int x) : Balance((double)x) {
cout <<"Constructor Act with parameter "<<x<<endl;
}
Finally, note that if you want to use the default value by omitting the parameter, but that your constructor has only one parameter, you should either use the syntax form a1 or a5 in the examples above. You should however not use the syntax with empty parentheses because this would be understood as a function declaration:
Act a0(); // Ouch !! function declaration ! Use a0 or a0{} instead.
In order to address your question we must break down what the line does.
The line calls the constructor for the class Act, the int which has no variable name requires the constructor to take an int. However the =0 part is the default parameter telling the constructor that you don't need the int just place a 0 there.
I am currently working on a project for class that requires us to implement a stack for integer use as a calculator. I am having problems with my default constructor and am wondering what I am missing.
OperandStack(int stackSize)
{
if (stackSize<=0)
{cout<<"Must be positive"<<endl;}
this->capacity=capacity;
s =new double[stackSize];
t=0;
}
Thanks for your help.
" I am having problems with my default constructor and am wondering what I am missing."
A default constructor takes no parameters, or declares default values for all of them. To cite from the linked reference documentation
Default constructors
A default constructor is a constructor which can be called with no arguments (either defined with an empty parameter list, or with default arguments provided for every parameter).
Thus your implementation should look like:
class OperandStack {
public:
OperandStack(int stackSize = 10)
// ^^^^ declare a default value
// Better use a member initializer list, instead of initializing claas
// members inside the constructor's body:
: capacity(stackSize), s(new double[stackSize]), t(0) {
if (stackSize<=0) {cout<<"Must be positive"<<endl;}
// ^^^^ Better use an exception instead of this
// output statement (it's OK for basic debugging)
}
};
There are four specific cases , where you must specify default initializer list.
Fully discussed here
In short, if you have
Initializer list Required
non-static const data members
data member of reference type
provide params to data members which are objects of other class
provide base class ctor parameters from derived class.
The one drawback to default argument seems to be that the default arguments must be the trailing parameters in the function prototype parameter list. For example:
drawbacks(???) to default arguments
void f(int, int = 2, int = 3); // trailing defaults
void g(int = 1, int = 2, int c); // error
void h(int, int = 3, int); // error
My question is, if my code does not fall in between the 4 required cases for initializer list and always requires all parameters to have default values, i.e. does not lead to the drawbacks to default arguments , which one should I choose and why? What is the best practice?
an example being
// option -1: for the default argument list
// my_array.h
my_array(int a_number_of_elements = 0, int default_val = 0);
//option-2 : default initalizer list
// my_array.h
my_array(int a_number_of_elements, int default_val);
//my_array.cpp
my_array:: my_array(int a_number_of_elements, int default_val)
: my_num_elements(a_num_elements), my_default_value(default_val)
Thanks for looking.
You are dealing with two completely different things here: constructor initializer lists vs default function arguments.
You got most of what you said correctly, but contrary to what you might believe, default constructor arguments do not imply the construction of data members using these values, unless you explicitly state so. Hence, one technique is not a replacement for the other, just separate complementary things.
For example:
// my_array.h
my_array(int a_number_of_elements = 1, int default_val = 0);
//my_array.cpp
my_array:: my_array(int a_number_of_elements, int default_val)
: my_num_elements(a_num_elements), my_default_value(default_val)
will [be expected to] initialize an array with one element of value zero.
If you do not explicitly call the constructors of the data members, then their default constructors, if available, will be called, so the following two are equivalent.
//implicitly default constructing members
my_array:: my_array()
{}
//explicitly default constructing members
my_array:: my_array() :
my_num_elements(), my_default_value()
{}
Regarding the two above, it is always a good idea to leave things explicit for better legibility. As often said, a given code is usually written once, but read many times.
You have a couple misconceptions here:
You are referring to "Constructor Initializer Lists" as initializer_lists
You seem to think that defaulted arguments can only be used separately from "Constructor Initialization Lists"
Lets talk about some principles here:
You'll always want to use a "Constructor Initializer List" for all your variables, not just those of the 4 types you mention. "Constructor Initializer Lists" value initialize, rather than default initializing and requiring you to assign to them in the constructor body
Where possible you'll always want to have a default constructor, as this is required for using your object in standard containers
Defaulting arguments is a great way to prevent code duplication for both a user defined constructor and a user defined default constructor
So using these principles I can say that the answer to your question is yes, that the ideal situation would be to to use both "Constructor Initializer Lists" and default arguments. Resulting in a constructor that looks something like:
my_array(int a_number_of_elements = 0, int default_val = 0) :
my_num_elements(a_number_of_elements),
my_default_value(default_val) {}