In C++, it's not possible to initialize array members in the initialization list, thus member objects should have default constructors and they should be properly initialized in the constructor. Is there any (reasonable) workaround for this apart from not using arrays?
[Anything that can be initialized using only the initialization list is in our application far preferable to using the constructor, as that data can be allocated and initialized by the compiler and linker, and every CPU clock cycle counts, even before main. However, it is not always possible to have a default constructor for every class, and besides, reinitializing the data again in the constructor rather defeats the purpose anyway.]
E.g. I'd like to have something like this (but this one doesn't work):
class OtherClass {
private:
int data;
public:
OtherClass(int i) : data(i) {}; // No default constructor!
};
class Foo {
private:
OtherClass inst[3]; // Array size fixed and known ahead of time.
public:
Foo(...)
: inst[0](0), inst[1](1), inst[2](2)
{};
};
The only workaround I'm aware of is the non-array one:
class Foo {
private:
OtherClass inst0;
OtherClass inst1;
OtherClass inst2;
OtherClass *inst[3];
public:
Foo(...)
: inst0(0), inst1(1), inst2(2) {
inst[0]=&inst0;
inst[1]=&inst1;
inst[2]=&inst2;
};
};
Edit: It should be stressed that OtherClass has no default constructor, and that it is very desirable to have the linker be able to allocate any memory needed (one or more static instances of Foo will be created), using the heap is essentially verboten. I've updated the examples above to highlight the first point.
One possible workaround is to avoid the compiler calling the OtherClass constructor at all, and to call it on your own using placement new to initialize it whichever way you need. Example:
class Foo
{
private:
char inst[3*sizeof(OtherClass)]; // Array size fixed. OtherClass has no default ctor.
// use Inst to access, not inst
OtherClass &Inst(int i) {return (OtherClass *)inst+i;}
const OtherClass &Inst(int i) const {return (const OtherClass *)inst+i;}
public:
Foo(...)
{
new (Inst(0)) OtherClass(...);
new (Inst(1)) OtherClass(...);
new (Inst(2)) OtherClass(...);
}
~Foo()
{
Inst(0)->~OtherClass();
Inst(1)->~OtherClass();
Inst(2)->~OtherClass();
}
};
To cater for possible alignment requirements of the OtherClass, you may need to use __declspec(align(x)) if working in VisualC++, or to use a type other than char like:
Type inst[3*(sizeof(OtherClass)+sizeof(Type)-1)/sizeof(Type)];
... where Type is int, double, long long, or whatever describes the alignment requirements.
What data members are in OtherClass? Will value-initialization be enough for that class?
If value-initialization is enough, then you can value-initialize an array in the member initialization list:
class A {
public:
A ()
: m_a() // All elements are value-initialized (which for int means zero'd)
{
}
private:
int m_a[3];
};
If your array element types are class types, then the default constructor will be called.
EDIT: Just to clarify the comment from Drealmer.
Where the element type is non-POD, then it should have an "accessible default constructor" (as was stated above). If the compiler cannot call the default constructor, then this solution will not work.
The following example, would not work with this approach:
class Elem {
public:
Elem (int); // User declared ctor stops generation of implicit default ctor
};
class A {
public:
A ()
: m_a () // Compile error: No default constructor
{}
private:
Elem m_a[10];
};
One method I typically use to make a class member "appear" to be on the stack (although actually stored on the heap):
class Foo {
private:
int const (&array)[3];
int const (&InitArray() const)[3] {
int (*const rval)[3] = new int[1][3];
(*rval)[0] = 2;
(*rval)[1] = 3;
(*rval)[2] = 5;
return *rval;
}
public:
explicit Foo() : array(InitArray()) { }
virtual ~Foo() { delete[] &array[0]; }
};To clients of your class, array appears to be of type "int const [3]". Combine this code with placement new and you can also truly initialize the values at your discretion using any constructor you desire. Hope this helps.
Array members are not initialized by default. So you could use a static helper function that does the initialization, and store the result of the helper function in a member.
#include "stdafx.h"
#include <algorithm>
#include <cassert>
class C {
public: // for the sake of demonstration...
typedef int t_is[4] ;
t_is is;
bool initialized;
C() : initialized( false )
{
}
C( int deflt )
: initialized( sf_bInit( is, deflt ) )
{}
static bool sf_bInit( t_is& av_is, const int i ){
std::fill( av_is, av_is + sizeof( av_is )/sizeof( av_is[0] ), i );
return true;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
C c(1), d;
assert( c.is[0] == 1 );
return 0;
}
Worth noting is that in the next standard, they're going to support array initializers.
Use inheritance for creating proxy object
class ProxyOtherClass : public OtherClass {
public:
ProxyOtherClass() : OtherClass(0) {}
};
class Foo {
private:
ProxyOtherClass inst[3]; // Array size fixed and known ahead of time.
public:
Foo(...) {}
};
And what about using array of pointers instead of array of objects?
For example:
class Foo {
private:
OtherClass *inst[3];
public:
Foo(...) {
inst[0]=new OtherClass(1);
inst[1]=new OtherClass(2);
inst[2]=new OtherClass(3);
};
~Foo() {
delete [] inst;
}
};
You say "Anything that can be initialized using only the initialization list is in our application far preferable to using the constructor, as that data can be allocated and initialized by the compiler and linker, and every CPU clock cycle counts".
So, don't use constructors. That is, don't use conventional "instances". Declare everything statically. When you need a new "instance", create a new static declaration, potentially outside of any classes. Use structs with public members if you have to. Use C if you have to.
You answered your own question. Constructors and destructors are only useful in environments with a lot of allocation and deallocation. What good is destruction if the goal is for as much data as possible to be allocated statically, and so what good is construction without destruction? To hell with both of them.
Related
Suppose I have a class with some constant member:
class MyClass {
public:
MyClass(int a) : a(a) {
}
MyClass() : MyClass(0) {
}
~MyClass() {
}
const int a;
};
Now I want to store an instance of MyClass somewhere, e.g. as a global variable or as an attribute of another object.
MyClass var;
Later, I want to assign a value to var:
var = MyClass(5);
Obviously, this does not work, because the assign operator is invoked, which does not exist by default, because MyClass has a const attribute. So far so good.
My question is, how can I assign a value to var anyway? After all, var itself is not declared to be a constant.
My thoughts so far
I know that the problem does not exist if I use a pointer for var:
MyClass *var;
var = new MyClass(5);
However, I would not like to use a pointer for convenience reasons.
A potential solution is to overwrite the memory with placement new:
template<class T, class... Args>
T &emplaceVar(T &myVar, Args&&... args) {
myVar.~T(); // free internal memory
return *new (&myVar) T(args...);
}
emplaceVar(var, 5);
This would solve the problem, but I am not sure if this may cause memory leaks or any other issues I have not thought of due to my lack of experience in c++. Furthermore, I would have thought there must be an easier way. Is there?
const members are problematic in general for the very reason you discovered.
The much simpler alternative is to make the member private and take care to provide no means to modify it from outside the class:
class MyClass {
public:
MyClass(int a) : a(a) {
}
MyClass() : MyClass(0) {
}
~MyClass() {
}
private:
int a;
};
I did not add a getter yet, because you say access via myObject.a is a hard requirement. Enabling this requires a bit of boilerplate, but it is much less hacky than modifiying something that must not be modified:
class MyClass {
public:
struct property {
const int& value;
operator int(){ return value;}
property(const property&) = delete;
};
MyClass(int a = 0) : value(a) {}
private:
int value;
public:
property a{value};
};
int main(){
MyClass myObject{5};
int x = myObject.a;
//myObject.a = 42; // error
//auto y = myObject.a; // unexpected type :/
}
Live Demo
Drawback is that it does not play well with auto. If by any means you can accept myObject.a() I would suggest to use that and keep it simple.
how can I assign a value to var anyway?
You can do that with a user-defined assignment operator:
class MyClass {
public:
MyClass &operator=(const MyClass &o)
{
// Implement your assignment here
return *this;
}
// ...
};
Your assignment operator can do anything that any operator= overload can. The only thing it can't do is assign anything to its const class member. That's because it's constant.
If a class does not have user-defined assignment operator, the default assignment operator assigns each member of the assigned-to object from the same member of the assigned-from object. However the default assignment operator is deleted from any class that has a const member, because that, of course, is no longer possible.
In your user-defined operator you can do whatever it means to assign one of these objects from another one. The only thing it can't do is the same thing any other class method can't do: modify a const class member.
You mentioned manual invocation of a destructor and placement new. That's possible, provided that all requisite requirements are met and undefined behavior is carefully avoided. However, technically, it wouldn't be assignment, but rather a manual destruction and construction of another object.
I have observed that the following code segfaults at the line ar.p():
#include <iostream>
class A
{
public:
virtual void p() { std::cout<<"A!\n"; }
};
class B : public A
{
public:
void p() { std::cout<<"B!\n"; }
};
struct Param
{
enum {AA, BB} tag;
union {
A a;
B b;
};
Param(const A &p)
: tag(AA) {a = p;}
A &get() {
switch(tag) {
case AA: return a;
case BB: return b;
}
}
};
int main() {
A a;
a.p();
Param u(a);
A &ar = u.get();
ar.p();
}
However, when I change the Param constructor to:
Param(const A &p)
: tag(AA), a(p) {}
it does not segfault anymore.
I think it has something to do with the way the vtable ptr for union member a is initialized, but I'd like to understand this bug better.
On coliru: http://coliru.stacked-crooked.com/a/85182239c9f033c1
The union doesn't have an implicit constructor, you have to add your own constructor to the union which initializes one of the members of the union. I think this is because the compiler can't know whether you want to initialize a or b. You may also need an assignment operator and destructor. See also this question: Why does union has deleted default constructor if one of its member doesn't have one whatsoever?
The constructor should use placement new or it can use a member initializer to construct one of the union members, as you do in your alternative constructor.
If you want to assign something to b afterwards, you have to destruct a using a.~A(), and then initialize b with placement new.
If you have members in the union with a non-trivial destructor then the union must have a destructor which calls the destructor on the member which is used at that point.
In your original code the assignment operator and the p() method are called without running a constructor first, leading to the crash.
As far as I know it is not possible to call the constructor of the base class. The only way I know is this:
MyClass::MyClass(/* args */) : Base(/* args */)
{
// ...
}
but this would invoke the constructor at the beginning.
Is there any way to call it somewhere else in the constructor? Something like this:
MyClass::MyClass(/* args */)
{
// ... instructions
Base::Base(/* args */);
// ... other_instructions
}
According to this What are the rules for calling the superclass constructor? question I understand there is no way but I read here and I guessed it was possible, but if I try I get:
error: invalid use of 'class Base'.
Am I doing something wrong? Is it possible to do this some way or is there any other possible solution to this need?
Thanks!
EDIT: I understand I forgot a key point: the base class is part of a framework, and therefore it would be good not to have to modify it, if possible.
If the base class constructor takes at least one argument, you could use a helper function like this:
int DoStuffBeforeCtorAndForwardInt(int arg, Foo foo)
{
DoStuff(arg, foo);
return arg;
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndForwardInt(arg, foo))
{
// ...
}
If you want to default-initialize the base class, you could use the copy-ctor to copy a default initialized base class instance:
Base DoStuffBeforeCtorAndReturnDefaultBase(int arg, Foo foo)
{
DoStuff(arg, foo);
return Base();
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndReturnDefaultBase(arg, foo))
{
// ...
}
Or, if Base doesn't have to be the first base class, you could derive MyClass from a helper class:
MyClass::MyClass(/* ... */)
: DoStuffHelperClass(/* ... */),
Base(/* ... */)
{
// ...
}
All of the above require that the "stuff" you do does not depend on the object that's about to be initialized (i.e. the functions can't safely be member functions and you cannot safely pass this as an argument to them either).
That means you can do some logging or similar, but then again you could also do that after the base class has been initialized.
(EDIT except with the DoStuffHelperClass solution, you can of course have members in DoStuffHelperClass, access them and what not)
Although I have to say that I can't recall ever using/needing/wanting something like that. It's quite probable that there is another (preferable) solution for what you're trying to do.
Use the base-from-member idiom to run your code before the ctor of the "real" base class (which is Base):
struct Base {
Base(string, int);
};
struct DerivedDetail {
DerivedDetail() {
value = compute_some_value();
value += more();
value += etc();
other = even_more_code(value);
}
string value;
int other;
};
struct Derived : private DerivedDetail, Base {
Derived() : Base(value, other) {}
// In particular, note you can still use this->value and just
// ignore that it is from a base, yet this->value is still private
// within Derived.
};
This works even if you don't have actual members you want in DerivedDetail. If you give more specifics on what you must do before the Base's ctor, then I can give a better example.
The base class is always fully constructed before construction of your own class begins. If you need to make a change to the state of the base class, you have to do that explicitly after it has been constructed.
Example:
MyClass::MyClass()
{
// Implicit call to Base::Base()
int result = computeSomething();
Base::setResult(result);
// ...
}
Besides the already written solutions, you can also use a static constructor function and make the contructor of MyClass private.
class QtBase{
// ...
};
class MyClass : public QtBase{
public:
// copy ctor public
MyClass(MyClass const& other);
static MyClass Create(/*args*/){
// do what needs to be done
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return MyClass(idata,fdata); // finally make them members
}
static MyClass* New(/*args*/){
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return new MyClass(idata,fdata); // finally make them members
}
private:
// ctor private
MyClass(int a_idata, float a_fdata)
: idata(a_idata)
, fdata(a_fdata)
{}
int idata;
float fdata;
};
Now you would have to create instances of MyClass either as:
MyClass obj = MyClass::Create(/*args*/);
or
MyClass* ptr = MyClass::New(/*args*/);
no, because it will not be type safe.
consider you have: a class A and a variable A.var.
now consider B inherits from A, and uses var before A was initialized. you will get a run time error! the language wants to prevent this, thus superclass constructor must be initialized first.
No, you can't do it that way, as other have described in their previous answers.
Your only chance is composition, IOW that MyClass uses Base class as a member field:
class MyClass {
public:
/** the methods... */
private:
Base* _base;
};
so you can initialize _base later, when you have the needed info. I don't know if this can apply to your scenario, anyway.
No. It is not possible, because the order of constructor calls is strictly defined by the standard. Base class ctor has to be executed before the derive class ctor can be executed.
Internally and about the generated code, is there a really difference between :
MyClass::MyClass(): _capacity(15), _data(NULL), _len(0)
{
}
and
MyClass::MyClass()
{
_capacity=15;
_data=NULL;
_len=0
}
thanks...
You need to use initialization list to initialize constant members,references and base class
When you need to initialize constant member, references and pass parameters to base class constructors, as mentioned in comments, you need to use initialization list.
struct aa
{
int i;
const int ci; // constant member
aa() : i(0) {} // will fail, constant member not initialized
};
struct aa
{
int i;
const int ci;
aa() : i(0) { ci = 3;} // will fail, ci is constant
};
struct aa
{
int i;
const int ci;
aa() : i(0), ci(3) {} // works
};
Example (non exhaustive) class/struct contains reference:
struct bb {};
struct aa
{
bb& rb;
aa(bb& b ) : rb(b) {}
};
// usage:
bb b;
aa a(b);
And example of initializing base class that requires a parameter (e.g. no default constructor):
struct bb {};
struct dd
{
char c;
dd(char x) : c(x) {}
};
struct aa : dd
{
bb& rb;
aa(bb& b ) : dd('a'), rb(b) {}
};
Assuming that those values are primitive types, then no, there's no difference. Initialization lists only make a difference when you have objects as members, since instead of using default initialization followed by assignment, the initialization list lets you initialize the object to its final value. This can actually be noticeably faster.
Yes. In the first case you can declare _capacity, _data and _len as constants:
class MyClass
{
private:
const int _capacity;
const void *_data;
const int _len;
// ...
};
This would be important if you want to ensure const-ness of these instance variables while computing their values at runtime, for example:
MyClass::MyClass() :
_capacity(someMethod()),
_data(someOtherMethod()),
_len(yetAnotherMethod())
{
}
const instances must be initialized in the initializer list or the underlying types must provide public parameterless constructors (which primitive types do).
I think this link http://www.cplusplus.com/forum/articles/17820/ gives an excellent explanation - especially for those new to C++.
The reason why intialiser lists are more efficient is that within the constructor body, only assignments take place, not initialisation. So if you are dealing with a non-built-in type, the default constructor for that object has already been called before the body of the constructor has been entered. Inside the constructor body, you are assigning a value to that object.
In effect, this is a call to the default constructor followed by a call to the copy-assignment operator. The initialiser list allows you to call the copy constructor directly, and this can sometimes be significantly faster (recall that the initialiser list is before the body of the constructor)
I'll add that if you have members of class type with no default constructor available, initialization is the only way to construct your class.
A big difference is that the assignment can initialize members of a parent class; the initializer only works on members declared at the current class scope.
Depends on the types involved. The difference is similar between
std::string a;
a = "hai";
and
std::string a("hai");
where the second form is initialization list- that is, it makes a difference if the type requires constructor arguments or is more efficient with constructor arguments.
The real difference boils down to how the gcc compiler generate machine code and lay down the memory. Explain:
(phase1) Before the init body (including the init list): the compiler allocate required memory for the class. The class is alive already!
(phase2) In the init body: since the memory is allocated, every assignment now indicates an operation on the already exiting/'initialized' variable.
There are certainly other ways to handle const type members. But to ease their life, the gcc compiler writers decide to set up some rules
const type members must be initialized before the init body.
After phase1, any write operation only valid for non-constant members.
There is only one way to initialize base class instances and non-static member variables and that is using the initializer list.
If you don't specify a base or non-static member variable in your constructor's initializer list then that member or base will either be default-initialized (if the member/base is a non-POD class type or array of non-POD class types) or left uninitialized otherwise.
Once the constructor body is entered, all bases or members will have been initialized or left uninitialized (i.e. they will have an indeterminate value). There is no opportunity in the constructor body to influence how they should be initialized.
You may be able to assign new values to members in the constructor body but it is not possible to assign to const members or members of class type which have been made non-assignable and it is not possible to rebind references.
For built in types and some user-defined types, assigning in the constructor body may have exactly the same effect as initializing with the same value in the initializer list.
If you fail to name a member or base in an initializer list and that entity is a reference, has class type with no accessible user-declared default constructor, is const qualified and has POD type or is a POD class type or array of POD class type containing a const qualified member (directly or indirectly) then the program is ill-formed.
If you write an initializer list, you do all in one step; if you don't write an initilizer list, you'll do 2 steps: one for declaration and one for asign the value.
There is a difference between initialization list and initialization statement in a constructor.
Let's consider below code:
#include <initializer_list>
#include <iostream>
#include <algorithm>
#include <numeric>
class MyBase {
public:
MyBase() {
std::cout << __FUNCTION__ << std::endl;
}
};
class MyClass : public MyBase {
public:
MyClass::MyClass() : _capacity( 15 ), _data( NULL ), _len( 0 ) {
std::cout << __FUNCTION__ << std::endl;
}
private:
int _capacity;
int* _data;
int _len;
};
class MyClass2 : public MyBase {
public:
MyClass2::MyClass2() {
std::cout << __FUNCTION__ << std::endl;
_capacity = 15;
_data = NULL;
_len = 0;
}
private:
int _capacity;
int* _data;
int _len;
};
int main() {
MyClass c;
MyClass2 d;
return 0;
}
When MyClass is used, all the members will be initialized before the first statement in a constructor executed.
But, when MyClass2 is used, all the members are not initialized when the first statement in a constructor executed.
In later case, there may be regression problem when someone added some code in a constructor before a certain member is initialized.
Here is a point that I did not see others refer to it:
class temp{
public:
temp(int var);
};
The temp class does not have a default ctor. When we use it in another class as follow:
class mainClass{
public:
mainClass(){}
private:
int a;
temp obj;
};
the code will not compile, cause the compiler does not know how to initialize obj, cause it has just an explicit ctor which receives an int value, so we have to change the ctor as follow:
mainClass(int sth):obj(sth){}
So, it is not just about const and references!
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 :)