I have a POD struct like so
struct foo {
std::mutex m_foo_mutex;
int a;
int b;
int c;
//......
};
It has more fields than this but the structure should be apparent. The default copy ctor is, of course, ill formed because std::mutex's copy ctor is delete.
It's perfectly fine for my uses to copy this object, and give the copied object a new mutex. So I have defined something like this inside foo.
foo(const foo &foo2) : m_foo_mutex() {
a = foo2.a;
b = foo2.b;
c = foo2.c;
//.......
}
That's all well but it's quite ugly when this struct has 20+ fields, normally the compiler would hide this from me. Is there a cleaner way to express this, or am I stuck with this big ugly constructor?
You could wrap just your mutex in a copyable class:
struct CopyableMutex {
std::mutex mutex;
CopyableMutex() = default;
CopyableMutex(const CopyableMutex&) {};
CopyableMutex& operator= (const CopyableMutex&) {
return *this;
};
};
struct foo {
CopyableMutex m_foo_mutex;
int a;
int b;
int c;
};
You might want to come up with a better name than CopyableMutex though, as obviously it isn't actually copying the mutex!
Suppose I have a class Foo, with a member variable that is a std::vector of floats, bar. I then create an instance of Foo, called foo. Let's say that I do not know the length of bar before the program runs, but at the point when foo's constructor is called, I know that it's length should be x.
There are three ways I can think of to initialize the length of bar, and I'm just wondering which of the three most people tend to use. I have ranked them in order of what I would consider to be "best practice", but I'm more curious about what method people "actually" use in practice. Sometimes I use methods which make the code clearer to follow, rather than necessarily following best practice...
bar is a private member, and I resize it during foo's constructor, e.g. Foo foo(x){bar.resize(x)};
bar is a private member, and I call foo.ResizeBar(x) which resizes bar internally, after creating foo.
bar is a public member, and I call foo.bar.resize(x), after creating foo.
Or, in code:
1.
class Foo
{
private:
std::vector<float> bar;
public:
Foo(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo(100);
return 0;
}
2.
class Foo
{
private:
std::vector<float> bar;
public:
Foo()
{
};
void ResizeBar(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo;
foo.ResizeBar(100);
return 0;
}
3.
class Foo
{
public:
std::vector<float> bar;
Foo()
{
};
};
int main()
{
Foo foo;
foo.bar.resize(100);
return 0;
}
The problem with all three of your methods is that you're needlessly invoking the default initializer for your vector, and then modifying the already initialized vector to suit your needs.
You should be invoking the correct initializer using the initializer list:
Foo::Foo(std::size_t x) : bar(x, 0) { }
The best method is not in the list of options you posted. The best method is to initialize bar using member initializer lists.
Foo::Foo(int x) : bar(x) {}
Whenever I define a variable and give it a value at the same time inside a class, I get an error. What is the reason for this?
As you can see, this doesn't work...
class myClass {
private:
int x = 4; // error
};
But when I keep the variable undefined it does:
class myClass {
private:
int x;
};
Since no one else is using member initialization, I'll introduce you:
class myClass {
private:
int x;
public:
myClass() : x (4){}
};
It's always better to use this over assigning in the body of the constructor, since by the time the body begins, all user-defined members will have already been initialized whether you said so or not. Better to do it once and actually initialize the non-user-defined members, and it is the only method that works for both non-static const members, and reference members.
For example, the following will not work because x isn't being initialized in the body, it's being assigned to:
class myClass {
private:
const int x;
public:
myClass() {x = 4;}
};
Using a member initializer, however, will, because you're initializing it off the bat:
class myClass {
private:
const int x;
public:
myClass() : x (4){}
};
Note also that your int x = 4; syntax is perfectly valid in C++11, where it subs in for any needed initialization, so you'll benefit if you start using it.
Initialize your variables in the constructor.
class myClass {
private:
int x;
public:
myClass()
{
x = 4; // hope that it will work
}
};
Updated Answer:
According to chris, it is better to use member initialization
class myClass {
private:
const int x;
public:
myClass() : x (4){}
};
Instance variable are supposed to be defined using setter methods, IE: setX(input) or inside a constructor.
Do this insted:
class myClass
{
private:
static const int x = 4;
};
If you don't x to be either static or constant, use only int x; instead and initialize x in the constructor of the class.
Your class is like a blue print. It does not have any storage associated with it. When you instantiate an object of your class, that is akin to the building based on that blue print. Your object has storage and that can hold the value you give to the member variables.
Also, as others have pointed out, it is possible to do what you want in C++11. Check out:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm
In C++03,
only static const integral data members can be initialized within a
class.
Either initialize in the constructor, or make the data member static const:
class myClass {
private:
int x;
public:
myClass() {
x = 4;
}
};
or
class myClass {
private:
static const int x = 4;
};
As a C# developer I'm used to running through constructors:
class Test {
public Test() {
DoSomething();
}
public Test(int count) : this() {
DoSomethingWithCount(count);
}
public Test(int count, string name) : this(count) {
DoSomethingWithName(name);
}
}
Is there a way to do this in C++?
I tried calling the Class name and using the 'this' keyword, but both fail.
C++11: Yes!
C++11 and onwards has this same feature (called delegating constructors).
The syntax is slightly different from C#:
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};
C++03: No
Unfortunately, there's no way to do this in C++03, but there are two ways of simulating this:
You can combine two (or more) constructors via default parameters:
class Foo {
public:
Foo(char x, int y=0); // combines two constructors (char) and (char, int)
// ...
};
Use an init method to share common code:
class Foo {
public:
Foo(char x);
Foo(char x, int y);
// ...
private:
void init(char x, int y);
};
Foo::Foo(char x)
{
init(x, int(x) + 7);
// ...
}
Foo::Foo(char x, int y)
{
init(x, y);
// ...
}
void Foo::init(char x, int y)
{
// ...
}
See the C++FAQ entry for reference.
Yes and No, depending on which version of C++.
In C++03, you can't call one constructor from another (called a delegating constructor).
This changed in C++11 (aka C++0x), which added support for the following syntax:
(example taken from Wikipedia)
class SomeType
{
int number;
public:
SomeType(int newNumber) : number(newNumber) {}
SomeType() : SomeType(42) {}
};
I believe you can call a constructor from a constructor. It will compile and run. I recently saw someone do this and it ran on both Windows and Linux.
It just doesn't do what you want. The inner constructor will construct a temporary local object which gets deleted once the outer constructor returns. They would have to be different constructors as well or you would create a recursive call.
Ref: https://isocpp.org/wiki/faq/ctors#init-methods
C++11: Yes!
C++11 and onwards has this same feature (called delegating constructors).
The syntax is slightly different from C#:
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};
C++03: No
It is worth pointing out that you can call the constructor of a parent class in your constructor e.g.:
class A { /* ... */ };
class B : public A
{
B() : A()
{
// ...
}
};
But, no, you can't call another constructor of the same class upto C++03.
In C++11, a constructor can call another constructor overload:
class Foo {
int d;
public:
Foo (int i) : d(i) {}
Foo () : Foo(42) {} //New to C++11
};
Additionally, members can be initialized like this as well.
class Foo {
int d = 5;
public:
Foo (int i) : d(i) {}
};
This should eliminate the need to create the initialization helper method. And it is still recommended not calling any virtual functions in the constructors or destructors to avoid using any members that might not be initialized.
If you want to be evil, you can use the in-place "new" operator:
class Foo() {
Foo() { /* default constructor deliciousness */ }
Foo(Bar myParam) {
new (this) Foo();
/* bar your param all night long */
}
};
Seems to work for me.
edit
As #ElvedinHamzagic points out, if Foo contained an object which allocated memory, that object might not be freed. This complicates things further.
A more general example:
class Foo() {
private:
std::vector<int> Stuff;
public:
Foo()
: Stuff(42)
{
/* default constructor deliciousness */
}
Foo(Bar myParam)
{
this->~Foo();
new (this) Foo();
/* bar your param all night long */
}
};
Looks a bit less elegant, for sure. #JohnIdol's solution is much better.
Simply put, you cannot before C++11.
C++11 introduces delegating constructors:
Delegating constructor
If the name of the class itself appears as class-or-identifier in the
member initializer list, then the list must consist of that one member
initializer only; such constructor is known as the delegating
constructor, and the constructor selected by the only member of the
initializer list is the target constructor
In this case, the target constructor is selected by overload
resolution and executed first, then the control returns to the
delegating constructor and its body is executed.
Delegating constructors cannot be recursive.
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};
Note that a delegating constructor is an all-or-nothing proposal; if a constructor delegates to another constructor, the calling constructor isn't allowed to have any other members in its initialization list. This makes sense if you think about initializing const/reference members once, and only once.
No, in C++ you cannot call a constructor from a constructor. What you can do, as warren pointed out, is:
Overload the constructor, using different signatures
Use default values on arguments, to make a "simpler" version available
Note that in the first case, you cannot reduce code duplication by calling one constructor from another. You can of course have a separate, private/protected, method that does all the initialization, and let the constructor mainly deal with argument handling.
Another option that has not been shown yet is to split your class into two, wrapping a lightweight interface class around your original class in order to achieve the effect you are looking for:
class Test_Base {
public Test_Base() {
DoSomething();
}
};
class Test : public Test_Base {
public Test() : Test_Base() {
}
public Test(int count) : Test_Base() {
DoSomethingWithCount(count);
}
};
This could get messy if you have many constructors that must call their "next level up" counterpart, but for a handful of constructors, it should be workable.
In Visual C++ you can also use this notation inside constructor: this->Classname::Classname(parameters of another constructor). See an example below:
class Vertex
{
private:
int x, y;
public:
Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
Vertex()
{
this->Vertex::Vertex(-1, -1);
}
};
I don't know whether it works somewhere else, I only tested it in Visual C++ 2003 and 2008. You may also call several constructors this way, I suppose, just like in Java and C#.
P.S.: Frankly, I was surprised that this was not mentioned earlier.
This approach may work for some kinds of classes (when the assignment operator behaves 'well'):
Foo::Foo()
{
// do what every Foo is needing
...
}
Foo::Foo(char x)
{
*this = Foo();
// do the special things for a Foo with char
...
}
I would propose the use of a private friend method which implements the application logic of the constructor and is the called by the various constructors. Here is an example:
Assume we have a class called StreamArrayReader with some private fields:
private:
istream * in;
// More private fields
And we want to define the two constructors:
public:
StreamArrayReader(istream * in_stream);
StreamArrayReader(char * filepath);
// More constructors...
Where the second one simply makes use of the first one (and of course we don't want to duplicate the implementation of the former). Ideally, one would like to do something like:
StreamArrayReader::StreamArrayReader(istream * in_stream){
// Implementation
}
StreamArrayReader::StreamArrayReader(char * filepath) {
ifstream instream;
instream.open(filepath);
StreamArrayReader(&instream);
instream.close();
}
However, this is not allowed in C++. For that reason, we may define a private friend method as follows which implements what the first constructor is supposed to do:
private:
friend void init_stream_array_reader(StreamArrayReader *o, istream * is);
Now this method (because it's a friend) has access to the private fields of o. Then, the first constructor becomes:
StreamArrayReader::StreamArrayReader(istream * is) {
init_stream_array_reader(this, is);
}
Note that this does not create multiple copies for the newly created copies. The second one becomes:
StreamArrayReader::StreamArrayReader(char * filepath) {
ifstream instream;
instream.open(filepath);
init_stream_array_reader(this, &instream);
instream.close();
}
That is, instead of having one constructor calling another, both call a private friend!
If I understand your question correctly, you're asking if you can call multiple constructors in C++?
If that's what you're looking for, then no - that is not possible.
You certainly can have multiple constructors, each with unique argument signatures, and then call the one you want when you instantiate a new object.
You can even have one constructor with defaulted arguments on the end.
But you may not have multiple constructors, and then call each of them separately.
When calling a constructor it actually allocates memory, either from the stack or from the heap. So calling a constructor in another constructor creates a local copy. So we are modifying another object, not the one we are focusing on.
Would be more easy to test, than decide :)
Try this:
#include <iostream>
class A {
public:
A( int a) : m_a(a) {
std::cout << "A::Ctor" << std::endl;
}
~A() {
std::cout << "A::dtor" << std::endl;
}
public:
int m_a;
};
class B : public A {
public:
B( int a, int b) : m_b(b), A(a) {}
public:
int m_b;
};
int main() {
B b(9, 6);
std::cout << "Test constructor delegation a = " << b.m_a << "; b = " << b.m_b << std::endl;
return 0;
}
and compile it with 98 std:
g++ main.cpp -std=c++98 -o test_1
you will see:
A::Ctor
Test constructor delegation a = 9; b = 6
A::dtor
so :)
If I have a simple struct Foo, defined like this, it's a POD:
#include <iostream>
#include <type_traits>
struct Foo {
int a;
int b;
bool c;
};
int main() {
std::cout << (std::is_pod<Foo>::value ? "POD" : "NON POD") << '\n'; // Prints "POD"
}
Now imagine I want to default initalize the members and directly do:
struct Foo {
int a;
int b;
bool c = true;
};
The struct is no longer a POD! Even with a constructor like this:
struct Foo {
int a;
int b;
bool c;
Foo() : a(0), b(0), c(false) {}
};
Foo has lost its PODness...
Now the tricky part begins. Imagine I want to add a constructor taking an a:
struct Foo {
int a;
int b;
bool c;
Foo(int a) : a(a), b(0), c(false) {}
};
Now Foo is definitely not a POD. BUT if a add a default constructor:
struct Foo {
int a;
int b;
bool c;
Foo() = default;
Foo(int a) : a(a), b(0), c(false) {}
};
Foo is now a POD!
So as you can see, even if I simply want to use a default value like in the second example, I lose the PODness, but I can regain it as long as I define an explicit default constructor.
So the question is: should we always add a default constructor so we can benefit from the PODness of the class and improve performance? It's too bad to lose performance just because I wanted to default initialize some members...
In other words, defining default value like in the second example makes the struct non POD and non trivial, which is bad performance-wise, so how can I default initialize values and keep the struct trivial? A simple solution would be to define an initFoo function that returns a default initialized Foo, like for example:
Foo initFoo() {
Foo foo;
foo.a = 0;
foo.b = 1;
foo.c = true;
return foo;
}
But this is not very C++, but is it the right thing to do anyway?
should we always add a default constructor so we can benefit from the PODness of the class
If you want a class to be POD, then it must be trivially default constructible, among the other requirements.
One way to achieve that requirement is to not declare any constructors nor default member initialisers. Another way is to define the default constructor as default. Latter is the only way if you want the class to have any non-default constructors.
It doesn't matter which approach you pick as far as PODness is concerned.
but is it the right thing to do anyway?
Your initFoo is a right way to return a Foo with specific values. Personally, I don't see value in the local variable, and would do this instead:
return {
0,
1,
true,
};
Unfortunately, we lose member names from the initialisers, at least until C++20 where we can write:
return {
.a = 0,
.b = 1,
.c = true,
};