In my code I am doing the following, but I am not sure if I am "allowed" to or if it is a good designing technique. I need to create an empty constructor, but I also need a constructor that initializes the variables given the parameters. So I am doing the following:
This is the C.h file.
class C
{
private:
string A;
double B;
public:
//empty constructor
C();
C(string, double);
}
And my C.cpp file:
//this is how I declare the empty constructor
C::C()
{
}
C::C(string a, double b)
{
A = a;
B = b;
}
Is the way I am declaring the empty constructor right or do I need to set A= NULL and B=0.0?
Your empty constructor does not do what you want. The double data member will not be zero-initialized unless you do it yourself. The std::string will be initialized to an empty string. So the correct implementation of the default constructor would simply be
C::C() : B() {} // zero-initializes B
Concerning the other constructor, you should prefer the initialization list:
C::C(const string& a, double b) : A(a), B(b) {}
otherwise, what you are doing is an assignment to default constructed objects.
In C++11 and later you can use the following to generate a default no-param constructor:
C() = default;
This is neater than C(){}.
This doesn't initialize members. In C++11 you can initialize members in the same line of declaration:
int m_member = 0; // this is a class member
Those 2 features avoids having to create your own no param constructor to default initialize members. So your class can look like this when applying those 2 features:
class C
{
private:
string A;
double B = 0;
public:
C() = default;
C(string, double);
}
It is fine to do this and leave the constructor empty, but you should be aware that uninitialized fields have undefined value. string is a class and it's default constructor takes care of its initialization, but double is not initialized here (in your defualt constructor), and its value is undefined (it may be whatever value previously exists in the memory).
A is std::string, you can't set it to NULL but can set to empty string and std::string has default constructor which initialize it to empty string by default.
C::C()
:B(0.0)
{
}
Maybe you need a constructor constructor with default parameter instead of two constuctors?
C(const string& a= "", double b= 0.0)
: A(a),
B(b)
{
}
You are the only person who can answer this question, because it depends entirely on your requirements for a default-constructed object. Since you haven't mentioned what your requirements are, it's not possible to give a definitive answer. Some people will guess that you should initialize B to 0, but that decision should be based on your design, not on various notions of "good" programming practice.
You can leave it as is. You can do this because both string and double can be default constructed. Meaning that you can say string foo; and not get any errors.
Contrast this with what happens here:
class Bar{
private:
Bar(); //Explicitly private;
};
Bar b;
Here we get an error about no constructor Bar::Bar() being found.
As to whether it's a good idea: It's hard to say without knowing the situation this class will be used in. Perhaps it's perfectly sensible to have it be in a unconfigured position. But for many classes, such as a class representing a file for example, allowing a file object which doesn't point to any file is obviously wrong.
You are doing it correct and you can see it by compiling your code. Your default constructor will initialize the string and double by calling their default constructors. If you define any constructor in your class it will hide the default constructor created by compiler for you.
You can improve your constructor code by writing it like this
C::C(string a, double b):A(a), b(b)
{
}
Related
Suppose I have the following class:
class A{
...
B obj;
C obj2
...
}
Upon construction of an A instance, B obj would be initialized by the default constructor. But before I can construct obj and obj2, I need to do some computation in the constructor of A and then call a non-default constructor for B obj and C obj2.
It does not cost me a lot, but the call to a default constructor for B obj and C obj2 upon construction of A would be completely unnecessary.
Can I prevent C++ from calling a default constructor? Or is this the wrong approach anyways?
EDIT: For clarification, I added a second object. I have to read from a file and can then construct B and C.
It is the somewhat wrong approach. I would suggest something like this:
int arguments(){ //assuming obj takes an int as 3rd constructor argument, could be any
//do computation you wanted to do in A::A
}
class A{
A() : obj(non, Default, arguments()){}
B obj;
}
Now the initialization is done before obj is created. You may also make arguments return a B and rely on the move constructor of B.
Edit: The answer does not change much with the edited question. Now you have two objects but the same logic applies:
class A{
A() : obj(doInitCalculations()), obj2(something){}
B obj;
C obj2;
}
obj must be initialized before obj2 (even if you write A() : obj2(), obj1{}) because they are constructed in the order they are declared in the class. So doInitCalculations is still called before either object is constructed.
You may delegate your constructor, something like:
class A
{
public:
A() : A(ComputeSomethingForBAndC()) {}
private:
A(const DataToBuildBAndC& dataToBuildBAndC) :
b(dataToBuildBAndC),
c(dataToBuildBAndC)
{}
private:
B b;
C c;
};
No matter what you do, the constructor of B will be called
before you enter into the body of A. If you don't specify
anything in the initializer list, the default constructor will
be called. If you need to calculate values first, then the only
real solution would be to do so in a static member function:
class A
{
B obj;
static B initializeB( ... );
public:
A( ... ) : obj( initializeB( ... ) ) {}
};
This is fine if the calculation only depends on the arguments,
and is only needed for the initialization of B. Otherwise, it
might require doing the same calculations twice.
If the initialization of B depends on other members, which are
also calculated, then you can put the other members before obj
(so they will be initialized first), and use the static member
trick on them. (Just be sure to put a big comment to the effect
that your code absolutely depends on the order of the members.)
Finally, if nothing else works, you can arrange for a "trivial"
constructor for B, which only does the minimum so that an
assignment later will work. Then you can write:
A::A()
: obj( doNothing )
{
// all the calculation
obj = B(...);
}
(For doNothing, just use an enum:
enum DoNothing { doNothing };
The provide an overload B::B( DoNothing ) in B.)
I'd consider this a last resort, as it involves modifying B,
which is rather invasive. Still, I've used it one or two times in the past.
You could use a (smart) pointer for B.
You'll need a level of indirection, something like:
class A {
unique_ptr<B> pObj;
public:
A {
// do your pre-B stuff
pObj = std::unique_ptr<B>(new B(/* args */));
};
// other stuff
}
I would recommend, make your B class constructor private.. something like
class B
{
private:
B();
}
and no one(from outside the class itself or friend classes) will be able to call default constructor. Also, then you'll have three options for using the class: either to provide a parameterized constructor, or use it as a utility class (one with static functions only), or to create a factory for this type in a friend class.
Can I prevent C++ from calling a default constructor?
You can't if B is not an build in or an aggregate Type.
I have two classes A and B, and in class A I have an member of type B:
class B {
public:
B(); //default constructor
};
class A {
public:
A(); //constructor
B b;
};
This is the definition of class A's constructor:
A::A() : b()
{}
Here, I tried to initialize b using the initialization list. My question is, is this way to initialize b correct, or am I just creating another temporary object named b inside the constructor of A that has nothing to do with A::b?
This is correct. However, since b is of class type, the default constructor will be called automatically if b isn't mentioned in A::A's initialization list, so you don't need to mention it at all.
This method will initialize the field b with the constructor B::B(). It does not create a temporary local.
Note that in this particular case it's also unnecessary. The default constructor generated for A will do this by itself. There is nothing wrong with being explicit here, it's just unnecessary
I'm new to C++, and the whole idea of classes - I'm still reading a book to try and learn. The book I'm reading says that when I construct a class, I can assign default values by doing this:
class foo {
public:
foo(char c, int i);
private:
char exampleChar;
int exampleInt;
};
foo::foo(char c, int i):
exampleChar(c),
exampleInt(i)
{}
This code (to me) looks very messy, and doesn't follow rules that I'm used to in other languages. My question is, what's the difference between doing the above, and this (below, which I personally think looks a lot cleaner)?
foo::foo(char c, int i) {
exampleChar = c;
exampleInt = i;
}
Sort of things I'm thinking about are: are there performance/efficiency issues if done on a large scale - or is it exactly the same?
The first way, by doing : exampleChar(c), exampleInt(i) is called an initializer list.
If you do it the second way, the two variables are default constructed first1, then you assign them a value. (When the actual body of the constructor is entered, anything that hasn't been initialized by the initializer list is default constructed.) This is a waste of time because you're just overwriting the values anyway. For small types like int or char this isn't a big deal, but when those member variables are large types that would take lots of cycles to construct, you definitely want to use the initializer list.
The second way won't waste time giving them a default value and then overwriting it - it will set their values directly to that value you give it (or call the right constructor if the member is an object).
You can see what we mean by doing this:
class MyClass {
public:
int _i; // our data
// default constructor
MyClass() : _i(0) { cout << "default constructor"; }
// constructor that takes an int
MyClass(int i) : _i(i) { cout << "int constructor"; }
// assignment operator
void operator=(int i) { _i = i; cout << "assignment operator"; }
};
class OtherClass {
public:
MyClass c;
OtherClass() {
c = 54;
}
};
OtherClass oc;
You'll see that
default constructor
assignment operator
is printed. That's two function calls which, for other classes, could be expensive.
If you change the constructor of OtherClass to
OtherClass() : c(54) { }
You'll see that
int constructor
is printed. Just one call compared to two. This is the most efficient way.
Initializer lists are also a must when you
have types that have no default constructor. You have to call the right constructor in the initializer list.
have a const member that you want to give some value (rather than just have permantently the default value
have a reference member. You must use initializer lists on these.
tl;dr: do it because it's at least as fast but never slower than the other way, and sometimes far faster.
1 For built in types like int and char, they are actually not constructed at all; they just have the value of whatever memory they happen to have had previously.
The difference is that the compiler will always initialize all members (in declaration order) prior to the first user-defined constructor statement. In the case of a char and an int, which are both primitive types, 'initialization' actually means 'no initialization' here. However, if you have a member with a constructor that does some actual work, this constructor will be called upfront - if you do
foo::foo() {
myComplexMember = MyComplexClass(42);
}
the compiler did already invoke the MyComplexClass default constructor before your code got called, which is a waste of resources (and a compiler error if the default ctor is not accessible).
By using an initialization list, you can customize the default initialization and avoid doing things for nothing. Obviously, this is the way to go.
There are things you can do like that that you couldn't otherwise.
If one of the members doesn't have a default constructor. That's the only way you could initiate the member at construction. (same goes to base class)
You can assign a value to a const member.
You can assure a defined state for the class before the constructor function starts running.
If a member is a reference it needs to be initialized in the Initialization List. Because references are immutable and can be initialized only once in the beginning (like const)
Well, this is a typical FAQ question: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6
In your case, using char and int there are no differences.
General rule: use initialization list as possibile, there are very few cases when you can prefer assignment, for example for improve readability:
MyClass::MyClass
{
a = b = c = d = e = f = 0;
}
is better than
class MyClass::MyClass : a(0), b(0), c(0), d(0), e(0), f(0) { }
If the members had non-trivial constructors, in the code below first the default constructors would be called, then the assignments would be executed, while in the code above they would be initialized only one time. So yes, there may be a performance issue.
There is also a practical issue: if they are const, references, or don't have default constructors, you can't use the version below.
There is a subtle, but important difference between those two options. What you have at the top is called a member initialization list. When the object is created, the members in this list are initialized to whatever you put in the parenthesis.
When you do assignment in the constructor body, the values are being first initialized, and then assigned. I'll post a short example below.
Example 1: Member initialization
class foo
{
public:
foo(char c, int i);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i):
exampleChar(c),
exampleInt(i),
exampleBar() //Here, a bar is being default constructed
{
}
Example 2: Constructor Assignment
class foo
{
public:
foo(char c, int i, Bar b);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i, Bar b):
//exampleChar(c),
//exampleInt(i),
//exampleBar()
{
exampleChar = c;
exampleInt = i;
exampleBar = someOtherBar; //Here, a bar is being assigned
}
This is where it gets interesting. Note that exampleBar is being assigned. Behind the scenes, a Bar is actually first being default constructed, even though you did not specify that. Furthermore, if your Bar is more complicated then a simple struct, you will need to be sure to implement the assignment operator in order for you to initialize it in this way. Even furthermore, in order to initialize the Bar from another Bar from the member initialization list, you must implement the copy constructor!
Example 3: Copy constructor used in member init
class foo
{
public:
foo(char c, int i, Bar b);
private:
char exampleChar;
int exampleInt;
Bar exampleBar;
};
foo::foo(char c, int i, Bar b):
//exampleChar(c),
//exampleInt(i),
exampleBar(b) //Here, a bar is being constructed using the copy constructor of Bar
{
exampleChar = c;
exampleInt = i;
}
I would get into the habit of using initialisation lists. They will not suffer from problems when somebody changes a char to some object where the default constructor is called first, and also for const correctness for the const values!
foo::foo(char c, int i):exampleChar(c),exampleInt(i){}
This construct is called a Member Initializer List in C++.
It initializes your member exampleChar to a value c & exampleInt to i.
What is the difference between Initializing And Assignment inside constructor? &
What is the advantage?
There is a difference between Initializing a member using initializer list and assigning it an value inside the constructor body.
When you initialize fields via initializer list the constructors will be called once.
If you use the assignment then the fields will be first initialized with default constructors and then reassigned (via assignment operator) with actual values.
As you see there is an additional overhead of creation & assignment in the latter, which might be considerable for user defined classes.
For an integer data type(for which you use it) or POD class members there is no practical overhead.
I'm wondering why I need to declare a default constructor in this case. For one thing doesn't the compiler do that automatically if i leave it out? And regardless, I still don't see why its necessary. Also, I get the error even if I omit 'obj_B = origin.obj_B;'
class B
{
public:
bool theArray[5] ;
B(bool x) {theArray[1] = x;};
//B(){};
};
class A
{
public:
B obj_B;
A() : obj_B(1) {};
A(A const &origin) {obj_B = origin.obj_B;}; //error:no matching function for call
//to B::B()
};
int main ()
{
std::vector <A> someAs;
for(int q=0;q<10;q++)
someAs.push_back(A());
for(int q=0;q<10;q++)
std::cout << someAs[q].obj_B.theArray[1] << std::endl;
}
The compiler only creates a default constructor if you don't specify an alternate constructor.
Because you made:
B(bool x) {theArray[1] = x;}
The default constructor will not be created for you.
The specific error you're getting is because A(A const &origin) doesn't specify the constructor to use for obj_B explicitly.
The following code would work:
A(A const &origin) : obj_B(1) {obj_B = origin.obj_B;}
By the way, you don't need a trailing semicolon on a function definition.
If you don't define any ctors for a class, the compiler will synthesize a default constructor. If you define another constructor though (e.g., one that takes an argument) then the compiler does not synthesize one for you, and you have to define one yourself.
In case you care, C++ 0x adds an "=default;" declaration to tell the compiler to provide a ctor that it would have provided by default, even if you have defined another ctor.
To define a copy constructor for A that does not require a default constructor for B, use member initializer syntax:
class A {
public:
A(A const& origin) : obj_B(origin.obj_B) {}
//...
};
To make one final point...
Assuming you hadn't defined a non-default constructor, failing to define a default constructor would've resulted in the elements of theArray[] being undefined. That is a bad habit to get into usually leading to bugs down the road.
With respect to the class definition for complex number, I saw two types of definitions:
Definition 1
class Complex
{
private:
double re;
double im;
public:
Complex(float r,float i) {re = r; im = i;}
~Complex() {};
};
Definition 2
class Complex
{
private:
double re;
double im;
public:
Complex(double r,double i): re(r), im(i) {}
~Complex() {};
};
The first definition looks OK to me but I do not quite understand the second definition, how does
Complex(double r,double i): re(r), im(i) {}
work? What does "re( )" mean?
It's called an initializer list. In a class's constructor, you can initialize member variables with this syntax. So in this, it's equivalent to putting the statements re = r; im = i; in the body of the constructor.
In the case of POD variables such as int, double, and pointer types, there is no difference between the initializer list syntax and regular assignments in the body. However, for const variables, references, and objects with non-trivial constructors, there is an important difference:
For const variables and reference variables, they must be initialized in the initializer list. They cannot be initialized by assigning to them in the body.
For objects with non-trivial constructors, how you initialize them in the initializer list corresponds to the constructor that gets called. If you omit the variable, then that object's default constructor gets called (if that object has no default constructor, then that is a compiler error).
Because of that, it's generally recommended that objects with constructors get initialized in the initializer list to avoid redundant work -- if you let its default constructor run by omitting it from the initializer list and then perform some sort of initialization in the constructor body, you're initializing it twice, which can be wasteful.
For example:
class Example
{
private:
std::string m_string;
public:
Example()
{
// m_string is first initialized by the std::string default constructor,
// then we assign to it with operator=(const char *).
// This is inefficient.
m_string = "test";
}
Example(int dummy)
: m_string("test")
{
// Better: we just call the std::string(const char*) constructor directly
}
};
The second form of the Complex constructor uses initialization lists, which are a different (and preferred way) of initialization class members.
The re(...) thing means that member field re should be constructed with whatever arguments it is passed.
As another example - you can create primitives like double and int like this:
double d(5.0d);
int i(5);
Which should explain how the parentheses work in the lists.
That's an initialization list. It sets the value of re to r and the value of im to i.
Generally you'll see a performance gain by using an initialization list, but it's also important to know when not to use it.
First of all, there should be a semicolon after the entire class definition in C++. Otherwise your code will fair to compile.
Anyway, the
Complex(double r,double i): re(r), im(i) {}
is a constructor for the Complex class that simply places the value of r into re and the value of i into im. That is another way of initializing a class's values.
Note that initialization lists like that can be very useful for initializing member classes within a class. Here's an example:
class MemberClass
{
private:
int mValue;
public:
MemberClass(int value): mValue(value) {}
};
class MemberHolder
{
private:
MemberClass mMember;
public:
MemberHolder(int value): mMember(value) {}
};
Initialization lists are important for using classes without a default constructor within other classes.
In C++ there is a distinction between assignment and initialization.
a = 5; // assignment
int b = 6; // initialization
int b(6); // also initialization
The first version of your class performs assignment inside the body of the constructor. This is more expensive, because the data members re and im are first default-constructed, and then are assigned their values.
In the second version constructor initialization list is used. Here the data members are initialized with the supplied values. This occurs in one step, while default constructor + assignment are two steps. This is more efficient.
Generally, you should prefer initializing your data members in the initialization list to assigning their values inside the body of the constructor. There is a caveat, though. The data member in the initialization list are initialized in the order in which they are declared in the class, not in the order in which they occur in the initialization list. Generally, you want the order of members in the list to match their order of declaration. Otherwise you may end up with very hard to find bugs if the initialization of one data member depends on the value of another.