I have derived class and base class. in the constructor of the derived class I have to use the basic constructor of the base class. Then later on I want to re-construct the base class with deiffernet base class constructor :
class A
{
public:
int a, b;
}
class B : public A
{
B() : A()
{
...
//do some calculations to calculate a and b and then
//re-construct class A with the right values.
A(a,b) <--- ????
}
}
how to I do that ?
Constructors are meant to create objects. Hence they are used once. You should create a method to do initialization and call that from constructors.
You could provide a copy and/or move assignment operations in class A.
class A
{
public:
int a, b;
// Copy assignment operator
A& operator=(const A& rhs) {
if(this == &rhs) return *this;
a = rhs.a; b = rhs.b;
return *this;
}
// ...
};
After the above you could reinitialize it using the pattern
BaseClass::operator=(BaseClass(a,b));
which, in your case is
A::operator=(A(a,b));
If your class is an aggregate, or has an implicitly defined copy constructor, you should use those (you don't have to define your own), and use the same reinitialization pattern as above.
As others already pointed out, you can only call inhereted constructors in the initialization list of your current constructor, or (in C++11) delegate to other constructors of your current class. This is the only place where you can initialize your class.
init method
In some cases it makes sense to add in init() method, which re-initializes parts of your class. This is called two-phase-initialization. You will find it in some window-managing-APIs.
It is important to note that your object is then separated into two parts: The one that is usefully initialized in the c'tor, and the other that is initialized in init(). You must (must, must must!) initialize both parts in a way that the object is in a consistent state -- in must never be in an invalid state. As a rule of thumb: If the object is created (by a c'tor), then a destructor call must always possible. Specificly: Don't leave any pointers and handles lying around with random values.
class ChildWindow : Compontent {
shared_ptr<Component> parent_; // builds the component hierarchy
Component[] children_; // child cp'nts, unknown during c'tor
size_t nchildren_; // ...use e vector in real code!
public:
ChildWindow(chared_ptr<>Component> parent)
: parent_(parent),
children(nullptr), nchildren(0) // MUST initialize
{}
void addChild(Component *child) { /*... change children_ ...*/ }
void init() {
if(nchildren > 0) { /* ...throw away old ... */ }
children_ = new Component[...];
// ... init children_ with nulls
}
};
This is only a rough idea where you may use two-phase initialization.
Wrapper
If you really just need to re-initialize everything, a technical solution might to use a simple wrapper class around you real object:
class WindowWrapper {
Window *window_;
public:
WindowWrapper() : window_(nullptr) {}
void reset() { delete window_; window_ = nullptr; }
Window& get() { return *window_; }
Window& operator*() { return get(); }
}
...typed down off-hand, probably some errors in it. This is why there already is such a wrapper in C++11:
unique_ptr<Window> win { new Window{parent, "title"} };
// ..use win...
win.reset( new Window{otherparent, "other title"} };
And if this unique_ptr is not enough you could put this inside the above wrapper.
The error
Just as a side note, To explain what the code you wrote does:
B::B() : A() {
A(a,b); // <--- ????
}
When you type line "????", you create a *temporary object of type A, which disappears on function exit. It does not call any destructor on your current object.
Why does it create a temp object? Well, you can write
A a(a,b);
as a statement and you get a new instance a of class A, constructed with the a c'tor with two arguments. This a you could use in another function call, say func(a);. But you can spare that explicit variable a by just leaving out its name:
func(A(a,b));
calls func with an unnamed ("temporary") object of class A, which disappears at the end of the statement (i.e. ;).
And these kind of temp objects you can create as an expression. And since every expression is also a statement
A(a,b);
is a valid statement -- creating a temp object, which immediately vanishes.
You cannot call the constructor of your superclass except in your initializer list. You have to use composition instead of inheritance if you want to use operations on a differrently constructed A object. If a method changes an already constructed object, it is not a contructor. So either replace the object with a newly constructed one (instead of changing it) or use non constructor methods.
Put the code to compute a and b into a method and use it in the initializer list:
class A {
public:
A(int a, int b): a_(a), b_(b) {}
};
class B : public A
{
public:
B(): A(B::computeA(), B::computeB()) {}
private:
static int computeA();
static int computeB();
};
I have made the methods static to prevent using a partially initialized object.
Although I have to say that the question and the example sound like you are using inheritance to re-use an implementation. In this case, you should not use inheritance but composition and replace the inheritance with a member object.
Related
Why did the creator of C++ decide to use constructor initializer list to initialize base classes? Why didn't he instead choose to use syntax like the second comment line in the following code?
class A{
public:
A() { }
};
class B : A{
public:
B() : A() { } // Why decide to use this one, using constructor initializer, to initialize base class?
B() { A(); } // Why not choose this one? It's easy for me to understand if it was possible.
};
int main(int argc, char *argv[]){
/* do nothing */
}
The advantage of using an initializer list is, that you have a completely initialized object in the body of the constructor.
class A {
public:
A(const int val) : val(val) { }
private:
const int val;
};
class B : A{
public:
B() : A(123) {
// here A and B are already initialized
}
};
So you have a guarantee that all members, even those of the parent, are not in an undefined state.
Edit
In the example of the question it is not necessary to call the base class in the initializer list, this is done automatically. So I slightly modified the example.
I can see a few possible alternatives to the current C++ rule that base classes and data members of a class type are initialised in the mem-initialiser list of the class type's constructor(s). They all come with their set of issues, which I will discuss below.
But first, note that you cannot simply write a derived constructor like this:
struct Derived : Base
{
Derived()
{
Base(42);
}
};
and expect the line Base(42); to call the base class constructor. Everywhere else in C++, such a statement creates a temporary object of type Base initialised with 42. Changing its meaning inside a constructor (or just inside its first line?) would be a syntax nightmare.
Which means that new syntax would need to be introduced for this. In the rest of this answer, I will use a hypothetical construct __super<Base> for this.
Now on to discuss possible approaches which would be closer to your desired syntax, and present their problems.
Variant A
Base classes are initialised in the constructor body, while data members are still initialised in the mem-initialiser list. (This follows the letter of your question the closest).
The would have the immediate problem of stuff executing in different order than it's written. For very good reasons, the rule in C++ is that base class subobjects are initialised before any data members of the derived class. Imagine this use case:
struct Base
{
int m;
Base(int a) : m(a) {}
};
struct Derived
{
int x;
Derived() :
x(42)
{
__super<Base>(x);
}
};
Written like this, you could easily assume x would be initialised first and then Base would be initialised with 42. However, that would not be the case and instead reading x would be undefined.
Variant B
Mem-initialiser lists are removed altogether, base classes are initialised using __super, and data members are simply assigned in the constructor body (pretty much the way Java does it).
This cannot work in C++ because initialisation and assignment are fundamentally different concepts. There are types where the two operations do vastly different things (e.g. references), and types which are not assignable at all (e.g. std::mutex).
How would this approach deal with a situtation like this?
struct Base
{
int m;
Base(int a) : { m = a; }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x); // This one's OK
r = *pd; // PROBLEM
}
};
Consider the line marked // PROBLEM. Either it means what it normally does in C++ (in which case it assigns a double into a "random place" which the uninitialised reference r references), or we change its semantics in constructors (or just in initial parts of a constructor?) to do initialisation instead of assignment. The former gives us a buggy program while the latter introduces totally chaotic syntax and unreadable code.
Variant C
Like B above, but introduce special syntax for initialising a data member in the constructor body (like we did with __super). Something like __init_mem:
struct Base
{
int m;
Base(int a) : { __init_mem(m, a); }
};
struct Derived : Base
{
double &r;
Derived(int x, double *pd)
{
__super<Base>(x);
__init_mem(r, *pd);
}
};
Now, the question is, what have we achieved? Previously, we had the mem-initialiser list, a special syntax to initialise bases and members. It had the advantage that it made clear these things happen first, before the constructor body starts. Now, we have a special syntax to initialise bases and members, and we need to force the programmer to put it at the start of the constructor.
Note that Java can get away with not having a mem-initialiser list for several reasons which don't apply to C++:
The syntax for creating an object is always new Type(args) in Java, whereas Type(args) can be used in C++ to construct objects by value.
Java only uses pointers, where initialisation and assignment are equivalent. For many C++ types, there operations are distinct.
Java classes can only have one base class, so using just super is enough. C++ would need to differentiate which base class you're referring to.
B() : A() { }
This will initialize the base class in user defined way.
B() { A(); }
This will NOT initialize the base class in user defined way.
This will create an object inside of constructor i.e B(){}
I think first initialization has better readability compared to the second and you can also deduce class hierarchy.
Normally one can change the order in which member initializers run by changing the order in which the members are declared in the class. However, is there a way to get the base class initializer/constructor to not run first?
This is a minimal sketch of my problem:
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg)
: member(expensiveFunction(arg))
, A(member) // <-- This will run first but I don't want it to
{}
private:
T member;
}
No, it is not possible. Class initialization is always like that: base class, members, this class constructor.
The reason for this is simple - since you can reference your members in this class constructor, you have to construct members before you call your constructor. Since you can reference your base class members from your members, you have to have them constructed before this class members.
Is it possible to run member initializers before base-class constructor?
Not as such.
That said, here are a few solutions:
1: move the member to an artificial base:
template<typename T>
class InitializerBase {
protected:
InitializerBase(T&& value) : member(std::move(value)) {}
T member;
};
class SpecialA: public InitializerBase<T>, public A {
public:
SpecialA(Arg *arg) : InitializerBase<T>(expensiveFunction(arg)): A{}
{
}
};
(Probably) the best solution would look like this:
2: use dependency injection for the fully constructed value (this is safest, best design and unless your code has bigger problems, most efficient implementation):
class SpecialA : public A {
public:
explicit SpecialA(T fully_computed_value)
: A(fully_computed_value)
, member(std::move(fully_computed_value)) // no heavy computations performed
{}
private:
T member;
}
Construction:
auto &a = SpecialA(expensiveFunction(arg));
This is the best solution because if expensiveFunction throws, you do not even start constructing the resulting object (the application doesn't have to release the resources for the half-constructed SpecialA).
Edit:That said, if you want to hide the use of the expensive function, the canonical solution to that (canonical because it is reusable, minimalistic and still respects good design) is to add a factory function:
SpecialA make_special(Arg *arg)
{
auto result = expensiveFunction(arg);
// extra steps for creation should go here (validation of the result for example)
return SpecialA( std::move(result) );
}
client code:
auto specialA = make_special(arg); // simplistic to call (almost as simple
// as calling the constructor directly);
// hides the use of the expensive function
// and provides max. reusability (if you
// need to construct a SpecialA without
// calling the expensive function, you
// can (by obtaining the constructor argument
// for SpecialA in a different way)
Just realized how to solve the problem:
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg) : SpecialA(arg, expensiveFunction(arg)) {}
private:
SpecialA(Arg* arg, T&& member) : A(member) , member(member) {};
T member;
}
Base class constructor must be called first.You cannot go any other way around but you can device a way to not make class A base class and call first whatever you want.
The base class is always fully constructed first. There is no way round this.
One alternative would be to break the inheritance and move the the base class to a member variable of the child class.
The order of member initialisation is then the order they appear in the class declaration.
But relying on this can make your code brittle, so do bear that in mind. Putting a suitable comment in the class declaration might not sufficiently discourage an enthusiastic refactorer.
The order of member initializers in the list is irrelevant: the actual
order of initialization is as follows:
1) If the constructor is for
the most-derived class, virtual base classes are initialized in the
order in which they appear in depth-first left-to-right traversal of
the base class declarations (left-to-right refers to the appearance in
base-specifier lists)
2) Then, direct base classes are initialized in
left-to-right order as they appear in this class's base-specifier list
3) Then, non-static data members are initialized in order of
declaration in the class definition.
4) Finally, the body of the
constructor is executed
Source: http://en.cppreference.com/w/cpp/language/initializer_list
in your case it looks like it would be more correct to invert the ownership of the item:
struct A
{
protected:
A(T expensive_object) : _expensive_object(std::move(expensive_object)) {}
protected:
T& access_expensive_object() {
return _expensive_object;
}
private:
T _expensive_object;
};
class SpecialA : public A {
public:
explicit SpecialA(Arg* arg)
: A(expensiveFunction(arg))
{}
void use_object() {
auto& o = expensive_object();
do_something_with(o);
}
};
Also you can use a reserved optional parameter as a placeholder:
class SpecialA : public A {
public:
SpecialA(Arg* arg, std::optional<T> reserved = {}) :
A(reserved = expensiveFunction(arg)),
member(reserved)
{}
private:
T member;
}
It can be better than delegating constructors because it bloats code less when there is a lot of parameters. Also there may be more overhead with delegating constructors (please, correct me if I'm wrong).
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 am pretty sure this is a simple question for a long time c++ user, this should be a pattern or the problem should be solved in any other way but given i am Python developer and a total novice with c++ i don't know how it's usually done.
Suppose that i have a class where i want to store a pointer to an object that can be of 1 of two different classes that respects an interface, for example:
class AllPlayers
{
public:
virtual void play();
};
class VlcPlayer: public AllPlayers
{
public:
virtual void play();
};
class Mplayer: public AllPlayers
{
public:
virtual void play();
};
class MyMediaPlayer
{
public:
MyMediaPLayer(int playerType);
AllPlayers m_player;
};
MyMediaPlayer::MyMediaPlayer(int PlayerType)
{
if (PlayerType == 0) {
VlcPlayer tmp_player;
m_player = static_cast<AllPlayers> (tmp_player);
}
else {
Mplayer tmp_player;
m_player = static_cast<AllPlayers> (tmp_player);
}
}
MyMediaPlayer test(0);
test.play();
First, i know this would not work and that it seems pretty normal why but how could i get this effect? i would like to have a member of a class for what i am going to use ever the same methods, implemented using a interface and i would like to avoid trying to cast to every of the derived classes every time i am going to use one of his methods.
C++ is value-based, i.e., if you create an object of a given type you really have an object of this type. This doesn't play nicely with dynamic polymorphism. To get dynamic polymorphism you use a pointer or a reference to the actual object. To also get the life-time straight you typicslly allocate the corresponding object on the stack (make sure your base class has a virtual destructor if you ever release an object of a derived type using a pointer to the base). With this, you should be all set: just call a virtual function of the base class through a pointer to rhe base: When you overridethe function in the derived class this is the function which is called.
If you write
AllPlayers m_player;
that is going to be an instance of AllPlayers and cannot be an instance of a class that derives from it.
You should instead use a pointer and allocate the class on the stack.
For example:
class MyMediaPlayer
{
public:
MyMediaPLayer(int playerType);
~MyMediaPLayer();
AllPlayers m_player;
};
MyMediaPlayer::MyMediaPlayer(int PlayerType)
{
if (PlayerType == 0) {
m_player = new VlcPlayer;
}
else {
m_player = new Mplayer;
}
}
MyMediaPlayer::~MyMediaPlayer()
{
if (0 != m_player) {
delete m_player;
m_player = 0;
}
}
As suggested by #xception use of unique_ptr may relieve you from having to write code to deallocate the instance.
As correctly pointed out by #DietmarKühl you should always declare a virtual destructor in a root class (a base class that does not itself derives from some other class) as is the case with AllPlayers.
class AllPlayers
{
public:
virtual ~AllPlayers();
virtual void play(); // note: this should probably be pure virtual.
};
The reason this will not work is colloquially known as Object Splicing. (Or, for those Harry Potter readers out there, Object Splinching)
Let's look at an example:
class Foo
{
public:
int bob;
float fred;
// Foo(const Foo& otherfoo); // implicit copy constructor
};
class Bar : public Foo
{
public:
double gabe; // gabe newell is fat
char steve; // steve jobs is thin
// Bar(const Bar& otherbar); // implicit copy constructor
};
int main()
{
Foo f;
Bar b;
f.bob = 10;
f.fred = 1.5;
b.bob = 15;
b.fred = 2.5;
b.gabe = 1.77245385091; // sqrt(pi)
b.steve = -4;
f = Foo(b);
return 0;
}
This is legal and valid. Problem is, the implicit copy constructor of Foo is called, and Foo's copy constructor knows nothing about what a Bar is. Only that it contains everything a Foo has, and some extra irrelevant crap. Because of this, only the Foo's data gets preserved; the data unique to the Bar gets spliced off.
It's important to note that this is DEFINED BEHAVIOR: it's doing EXACTLY WHAT YOU TELL IT TO. Casting between a subclass of a base class and a base class is implicit. Furthermore, the behavior of the copy constructor is implicit.
It's also important to note that, under the hood, C++ pointers and references work in the same way. It's perfectly sane to pass the Bar to Foo's copy constructor by reference, this pass by reference does not produce a copy of the object. It's the same as working with a pointer.
The actual splicing takes place as a direct result of the copy constructor biting off more than it can chew. It gets an object with more state than it expected, and its only choice is to ignore the extra state.
With python, this doesn't happen because everything is implicitly stored as a reference type. Since you only work with references (the objects themselves are abstracted away), you never have the opportunity to accidentally splice an object.
I'm confused with the this keyword in C++, I'm not sure that if I'm doing the right thing by passing this. Here is the piece of code that I'm struggling with:
ClassA::ClassA( ClassB &b) {
b.doSth(this);
// trying to call b's routine by passing a pointer to itself, should I use "this"?
}
ClassB::doSth(ClassA * a) {
//do sth
}
You're using it correctly. The this pointer points to the current object instance.
class helper
{
public:
void help(worker *pWorker) {
//TODO do something with pWorker . . .
}
void help2(worker& rWorker) {
//TODO do something with rWorker . . .
}
};
class worker
{
public:
void dowork() {
//this one takes a worker pointer so we can use the this pointer.
helper.help(this);
//to pass by reference, you need to dereference the this pointer.
helper.help2(*this);
}
helper helper;
};
Also, say you declare worker *pW = new worker(). If you call one of the methods (dowork) on the pW object, you will notice that the this pointer and pW have the exact same value (they are both the same address).
(haven't tested that to make sure it builds, but I think it should).
In C++, this is a keyword which is defined as "the pointer to the current object instance". So your code above is correct.
Depending on the inheritance/composition relationship between ClassA and ClassB, there are probably better ways to achieve what you are doing than by using the this pointer.
It's perfectly OK to pass 'this' or '*this' as you are doing.
Lifetime Dangers:
One point about the example you've supplied is that you're calling doSth from the constructor of ClassA. The object that's passed to doSth is possibly a partially constructed object:
class ClassC {
public:
ClassC ()
: m_c ()
{}
int m_c;
};
class ClassA : public ClassC {
public:
ClassA (ClassB & b)
: ClassC ()
, m_b ( b.doSth (this) ) // ClassC constructed
// ClassA members partially init.
{
b.doSth (this); // ClassA members initialized
}
// ...
int m_a;
};
class ClassD : public ClassA {
public:
ClassD(ClassB & b)
: ClassA (b) // Partially init
, m_d ()
{
// ClassC and ClassA constructed
// ClassD members initialized
}
int m_d;
};
There may be problems if doSth uses members that have not yet been initialized:
void ClassB::doSth (ClassA * a) {
int i = a->m_c; // OK m_c is initialized
int j = a->m_a; // Not OK, m_a not initialized when called
// from member initialization list.
int k = static_cast<ClassD*> (a).m_d; // Not OK
}
Using the dynamic type of the object:
Finally, any use of the dynamic type of the object (eg. virtual calls, dynamic_cast, typeid) will have different results on a partially constructed object than on a complete object (and in some case you can have undefined behaviour).
void ClassB::doSth (ClassA * a) {
if (ClassD * d = dynamic_cast<ClassD *> (a))
{
// Never true when called from ClassA::ClassA
}
}
In this case using this will pass a pointer to the caller class, which is A, to b.DoSth. It seems that you are doing it right. this keyword always points to the class instance that you are using it from.
this is a const pointer to its own object. this pointer is nonmodifiable.
ClassA::ClassA( ClassB &b) {
b.doSth(this);
// here 'this' refers to this object ie the instance of ClassA.
// When you pass 'this' to doSth function --> is equivalent to passing
// the instance of current object of ClassA.
//
}
If what you want is to make it the this as in thiscall, or, the actual very first parameter of any member functions (for g++), there is only one way: by the member access operators:
A* a = sth_that_give_you_an_A();
((B*)a)->doSth();
or in your case, if you want to pass the instance of class A to B::doSth.
((B*)this)->doSth();
Or, you may want to cast it to void* first to make your compiler happy.
If this is what you actually want, it is somehow the only way to do that.
However, an instance of class A may not also be an instance of class B. It is very rare that you want actually do this. You should find a proper way that allow you to down cast an instance of A to its subclass B with confidence.
Or otherwise, if you want to call B::doSth on the instance of B, it is just as normal as what you may do.
this is a pointer to the object instance, so what you are doing is correct.
Read this for more information.