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.
Related
Is using the cast constructor bad?
Otherweise why a code quality checker (cppcheck in my case) would constantly suggest to add explicit before single parameter constructors?
What if I want to do
class MyClass {
A(int) {}
};
A a = 1;
If I follow the "suggestions" and write
class MyClass {
explicit A(int) {}
};
A a = 1;
would throw an error, but if I use the first I'll have a warning that i've to document to pass the code reviews.
C++ Core Guidelines
C.46: By default, declare single-argument constructors explicit
Reason
To avoid unintended conversions.
Example, bad
class String {
public:
String(int); // BAD
// ...
};
String s = 10; // surprise: string of size 10
Exception
If you really want an implicit conversion from the constructor
argument type to the class type, don't use explicit:
class Complex {
public:
Complex(double d); // OK: we want a conversion from d to {d, 0}
// ...
};
Complex z = 10.7; // unsurprising conversion
See also: Discussion of implicit conversions
Such implicit class type conversion can be used easily without intention. With this converting constructor every function or member function which accepts MyClass as argument will accept also int. Therefore every int passed to such a function will be converted to a temporary MyClass which will be discarded after the function has finished. Probably not what you want.
Say i have the following class :
class A
{
public:
A() {
}
A(int a):_a(a){
}
int _a;
};
And the following function :
void someFunc (A a)
{
cout << a._a;
}
So the following line in the program works fine :
someFunc (5); // Calls A(int a) Constructor.
But the following does not :
someFunc(); //Compile error
One can expect that if it can build A when getting an integer,
why not build one using the default constructor as well, when called with no arguments?
Because someFunc() requires an argument and you have not provided an overload which does not. An implicit conversion from int to A exists, but that doesn't mean you can just ignore the function's signature and call it with no arguments. If you would like to call it with no arguments them assign a default value to a.
void someFunc(A a = A()) {
/* stuff */
}
Because you didn't call the function with an argument that turned out to be convertible, you called the function with no arguments. That's a different overload, one you haven't provided.
Consider these options:
Call the function like this: someFunc(A()).
Define a default value for the function parameter: void someFunc (A a = A()) { ... }.
Provide the no-argument overload: void someFunc() { someFunc(A()); }
This is because the signature of someFunc() does not match that of void someFunc (A a).
According to C++ standard, Section 13.3.2.3:
First, to be a viable function, a candidate function shall have enough parameters to agree in number with the arguments in the list.
A candidate function having more than m parameters is viable only if the (m+1)-st parameter has a default argument
None of this applies in this case, so void someFunc (A a) is not considered viable for the invocation with an empty parameter list.
Nitpick. From the 2003 C++ Standard,
17.4.3.2.1 Global names - ...
- Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace
I would tell you that it's poor practice to start any variable name with _. Especially as you may extend that practice into named variable arguments (int foo(int _a)), or do it with camelcase without thinking (int _MyVar). I personally do things like
int a_;
Will you ever actually have trouble? Probably not. But it's good practice not to start your anything with an underscore. Never with two underscores anywhere in the name, or started by an underscore followed by an uppercase letter, of course, too.
I'm not really providing an answer here, but it's useful information all the same... There are times when you really don't want to allow someFunc(5) to work, because it might lead to incorrect operation, or simply be misleading. In such cases you can declare the constructor as explicit:
class A
{
public:
A() {} // Are you sure you don't want to initialise _a here?
explicit A(int a) :_a(a) {}
int _a;
};
And as others have already said you can specify a default parameter for someFunc:
void someFunc( A a = A() );
Now:
someFunc(); // Calls A() by default
someFunc(5); // Not allowed because of implicit construction
someFunc(A(5)); // Caller must pass an instance of A
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.
I understand that constructors with one (non-default) parameter act like implicit convertors, which convert from that parameter type to the class type. However, explicit can be used to qualify any constructor, those with no parameters (default constructor) or those with 2 or more (non-default) parameters.
Why is explicit allowed on these constructors? Is there any example where this is useful to prevent implicit conversion of some sort?
One reason certainly is because it doesn't hurt.
One reason where it's needed is, if you have default arguments for the first parameter. The constructor becomes a default constructor, but can still be used as converting constructor
struct A {
explicit A(int = 0); // added it to a default constructor
};
C++0x makes actual use of it for multi parameter constructors. In C++0x, an initializer list can be used to initialize a class object. The philosophy is
if you use = { ... }, then you initialize the object with a sort of "compound value" that conceptually represents the abstract value of the object, and that you want to have converted to the type.
if you use a { ... } initializer, you directly call the constructors of the object, not necessarily wanting to specify a conversion.
Consider this example
struct String {
// this is a non-converting constructor
explicit String(int initialLength, int capacity);
};
struct Address {
// converting constructor
Address(string name, string street, string city);
};
String s = { 10, 15 }; // error!
String s1{10, 15}; // fine
Address a = { "litb", "nerdsway", "frankfurt" }; // fine
In this way, C++0x shows that the decision of C++03, to allow explicit on other constructors, wasn't a bad idea at all.
Perhaps it was to support maintainance. By using explicit on multi-argument constructors one might avoid inadvertently introducing implicit conversions when adding defaults to arguments. Although I don't believe that; instead, I think it's just that lots of things are allowed in C++ simply to not make the language definition more complex than it already it is.
Perhaps the most infamous case is returning a reference to non-static local variable. It would need additional complex rules to rule out all the "meaningless" things without affecting anything else. So it's just allowed, yielding UB if you use that reference.
Or for constructors, you're allowed to define any number of default constructors as long as their signatures differ, but with more than one it's rather difficult to have any of them invoked by default. :-)
A better question is perhaps, why is explicit not also allowed on conversion operators?
Well it will be, in C++0x. So there was no good reason why not. The actual reason for not allowing explicit on conversion operators might be as prosaic as oversight, or the struggle to get explicit adopted in the first place, or simple prioritization of the committee's time, or whatever.
Cheers & hth.,
It's probably just a convenience; there's no reason to dis-allow it, so why make life difficult for code generators, etc? If you checked, then code generation routines would have to have an extra step verifying how many parameters the constructor being generated has.
According to various sources, it has no effect at all when applied to constructors that cannot be called with exactly one argument.
According to the High Integrity C++ Coding Standard you should declare all sinlge parameter constructor as explicit for avoiding an incidentally usage in type conversions. In the case it is a multiple argument constructor suppose you have a constructor that accepts multiple parametres each one has a default value, converting the constructor in some kind of default constructor and also a conversion constructor:
class C {
public:
C( const C& ); // ok copy
constructor C(); // ok default constructor
C( int, int ); // ok more than one non-default argument
explicit C( int ); // prefer
C( double ); // avoid
C( float f, int i=0 ); // avoid, implicit conversion constructor
C( int i=0, float f=0.0 ); // avoid, default constructor, but
// also a conversion constructor
};
void bar( C const & );
void foo()
{
bar( 10 ); // compile error must be 'bar( C( 10 ) )'
bar( 0.0 ); // implicit conversion to C
}
One reason to explicit a default constructor is to avoid an error-prone implicit conversion on the right hand side of an assignment when there is an overload to class_t::operator= that accepts an object with type U and std::is_same_v<U, class_t> == false. An assignment like class_t_instance = {} can lead us to an undesirable result if we have, for example, an observable<T> that overloads the move assignment operator to something like observable<T>::operator=(U&&), while U should be convertible to T. The confusing assignment could be written with an assignment of a default constructed T (observed type object) in mind, but in reality the programmer is "erasing" the observable<T> because this assignment is the same as class_t_instance = class_t_instance{} if the default constructor is implicit. Take a look at a toy implementation of an observable<T>:
#include <boost/signals2/signal.hpp>
#include <iostream>
#include <type_traits>
#include <utility>
template<typename T>
struct observable {
using observed_t = T;
//With an implicit default constructor we can assign `{}` instead
//of the explicit version `observable<int>{}`, but I consider this
//an error-prone assignment because the programmer can believe
//that he/she is defining a default constructed
//`observable<T>::observed_t` but in reality the left hand side
//observable will be "erased", which means that all observers will
//be removed.
explicit observable() = default;
explicit observable(observed_t o) : _observed(std::move(o)) {}
observable(observable&& rhs) = default;
observable& operator=(observable&& rhs) = default;
template<typename U>
std::enable_if_t<
!std::is_same_v<std::remove_reference_t<U>, observable>,
observable&>
operator=(U&& rhs) {
_observed = std::forward<U>(rhs);
_after_change(_observed);
return *this;
}
template<typename F>
auto after_change(F&& f)
{ return _after_change.connect(std::forward<F>(f)); }
const observed_t& observed() const noexcept
{ return _observed; }
private:
observed_t _observed;
boost::signals2::signal<void(T)> _after_change;
};
int main(){
observable<int> o;
o.after_change([](auto v){ std::cout << "changed to " << v << std::endl; }); //[1]
o = 5;
//We're not allowed to do the assignment `o = {}`. The programmer
//should be explicit if he/she desires to "clean" the observable.
o = observable<int>{};
o = 10; //the above reaction [1] is not called;
//outputs:
//changed to 5
}
I'm reading this C++ open source code and I came to a constructor but I don't get it ( basically because I don't know C++ :P )
I understand C and Java very well.
TransparentObject::TransparentObject( int w, int x, int y, int z ) :
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
{
int bla;
int bla;
}
As far I can "deduce" The first line only declares the construtor name, the "::" sounds like "belongs to" to me. And the code between {} is the constructor body it self.
I "think" what's after the paremeters and the first "{" are like methods default parameters or something, but I don't find a reasonable explanation on the web. Most of the C++ constructors that I found in the examples are almost identical to those in Java.
I'm I right in my assumptions? "::" is like belongs to, and the list after params and body are like "default args" or something?
UPDATE:
Thanks for the answers.
May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body
The most common case is this:
class foo{
private:
int x;
int y;
public:
foo(int _x, int _y) : x(_x), y(_y) {}
}
This will set x and y to the values that are given in _x and _y in the constructor parameters. This is often the best way to construct any objects that are declared as data members.
It is also possible that you were looking at constructor chaining:
class foo : public bar{
foo(int x, int y) : bar(x, y) {}
};
In this instance, the class's constructor will call the constructor of its base class and pass the values x and y.
To dissect the function even further:
TransparentObject::TransparentObject( int w, int x, int y, int z ) :
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
{
int bla;
int bla;
}
The ::-operator is called the scope resolution operator. It basically just indicates that TransparentObject is a member of TransparentObject. Secondly, you are correct in assuming that the body of the constructor occurs in the curly braces.
UPDATE: Thanks for the answers. May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body
There is much more information on this subject than I could possibly ever give you here. The most common area where you have to use initializer lists is when you're initializing a reference or a const as these variables must be given a value immediately upon creation.
You are pretty close. The first line is the declaration. The label left of the :: is the class name and for it to be a constructor, the function name has to be the same as the class name.
TransparentObject::TransparentObject( int w, int x, int y, int z )
In C++ you can optionally put a colon and some initial values for member variables before the start of the function body. This technique must be used if you are initialzing any const variables or passing parameters to a superclass constructor.
:
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
And then comes the body of the constructor in curly braces.
{
int bla;
int bla;
}
:: Actually means contains (see comments for clarification), however the _someMethods and so forth is what's called an initialisation list. There is plenty of info at the link =]
EDIT: Sorry, my first sentence is incorrect - see the comments.
Yes, :: is the C++ scoping operator which lets you tell the compiler what the function belongs to. Using a : after the constructor declaration starts what is called an initialization list.
The code between the argument list and the {}s specifies the initialization of (some of) the class members.
Initialization as opposed to assignment---they are different things---so these are all calls to constructors.
You're correct. Its a way to set the default values for the class variables. I'm not too familiar with the exact difference between putting them after : and in the function body.
There are usually some good reasons to use an initialization list. For one, you cannot set member variables that are references outside of the initialization list of the constructor. Also if a member variable needs certain arguments to its own constructor, you have to pass them in here. Compare this:
class A
{
public:
A();
private:
B _b;
C& _c;
};
A::A( C& someC )
{
_c = someC; // this is illegal and won't compile. _c has to be initialized before we get inside the braces
_b = B(NULL, 5, "hello"); // this is not illegal, but B might not have a default constructor or could have a very
// expensive construction that shouldn't be done more than once
}
to this version:
A::A( C& someC )
: _b(NULL, 5, "hello") // ok, initializing _b by passing these arguments to its constructor
, _c( someC ) // this reference to some instance of C is correctly initialized now
{}
Without using the initialiser list all class members will simply have their default constructor called so this is the only place that you can control which constructor is called (for non-dynamically allocated members). The same is true for which parent class constructor will be called.
Class members "initialised" within the body of the constructor (i.e. between the {} braces using the = operator) isn't technically initialisation, it's an assignment. For classes with a non-trivial constructor/destructor it can be costly to default construct and then modify through assignment in this way. For reference members you must use the initialiser list since they cannot be changed via the assignment operator.
If the member (or parent class) does not have a default constructor then failing to specify an appropriate constructor in the initialiser list will cause the compiler to generate an error. Otherwise the compiler will insert the default constructor calls itself. For built in types this does nothing so you will have garbage values there.
Note that the order in which you specify the members in the initialiser list does not affect the order in which they are called. It is always the parent class constructor (if any) first, then the class members in the order in which they are defined in the class definition. The order in which you put them in the initialiser list does not matter and can be the source of subtle bugs...
In the contrived example below it looks like the intention is to initialise m_b with value then m_a with m_b, but what actually happens is that m_a is initialised with m_b (which is itself not yet initialised) then m_b gets initialised with value. m_b will just contain garbage!
struct BadInitialiserListExample
{
BadInitialiserListExample(int value) :
m_b(value),
m_a(m_b) // <-- *BUG* this is actually executed first due to ordering below!
{
}
int m_a;
int m_b;
};