Are there any issues when passing 'this' to another object in the initializer list in the following code?
class Callback { public: virtual void DoCallback() = 0; };
class B
{
Callback& cb;
public:
B(Callback& callback) : cb(callback) {}
void StartThread();
static void Thread()
{
while (!Shutdown())
{
WaitForSomething();
cb.DoCallback();
}
}
};
class A : public Callback
{
B b;
public:
A() : b(*this) {b.StartThread();}
void DoCallback() {}
};
If it is unsafe to do that, what's the best alternative?
An initialization list can be used to explicitly call a constructor that takes arguments for a data member that is an object of another class (see the employee constructor example above). In a derived class constructor, an initialization list can be used to explicitly call a base class constructor that takes arguments.
Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.
As already answered, initialization lists get completely executed before entering the constructor block. So it is completely safe to use (initialized) members in the constructor body.
Initialization lists allow you to choose which constructor is called and what arguments that constructor receives. If you have a reference or a const field, or if one of the classes used does not have a default constructor, you must use an initialization list.
If the other class just stores the pointer/reference, like in your case, it is safe. But you have to be sure that the constructors/functions you pass this
to are not trying to access the referenced object before A
's constructor finishes. The A
object is not fully constructed yet and calling methods of A
and accessing properties might lead to undefined results.
If you are extremely careful this will work fine. You will get into a lot of trouble if you start calling virtual methods or using methods which depend on other objects in the type. But if you're just setting a reference this should work fine.
A safer (but not completely safe) alternative is to set b later on once the constructor is completed. This won't eliminate vtable issues but will remove problems like accessing other member variables before they are constructed.
class A : public Callback {
std::auto_ptr<B> spB;
public:
A() {
spB.reset(new B(this));
spB->StartThread();
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With