Reputation: 31
I want to call a constructor of a member object in the owners constructor, but can not construct the member object in the initializer-list because of dependencies. How can I call the constructer after my initializations? I would really like to not use an init method
Upvotes: 3
Views: 1502
Reputation: 218333
want to call a constructor of a member object in the owners constructor, but can not construct the member object in the initializer-list because of dependencies
You might modify your class to have correct dependency order, and maybe use delegating constructor:
So turning:
struct S
{
S(/*..*/) : /*m1(data), m2(data),*/ data(/*..*/) // Issue, m1, m2 constructed before data
{
ComplexData2 data2 = Query();
m1.init(data, data2.someField1); // Doesn't like init method
m2.init(data, data2.someField2); // Doesn't like init method
}
Member1 m1; // Cannot be const with init method :/
Member2 m2; // Cannot be const with init method :/
ComplexData data;
};
into
struct S
{
S(/*..*/) : S(Query() /*, ..*/) {}
// private: // probably private
S(const ComplexData2& data2 /*, ..*/) :
data(/*..*/),
m1(data, data2.someField1),
m2(data, data2.someField2)
{
}
public:
ComplexData data; // Before m1, m2 for dependencies.
/*const*/ Member1 m1; // Can be const
/*const*/ Member2 m2; // Can be const
};
Upvotes: 0
Reputation: 2558
You have two options: either use dynamic storage, or placement new.
The first one is obvious (as pointed out in comments, you can use unique_ptr
). If you want to avoid this, you might try placement new with std::aligned_union
as storage:
class SomeClass { ... };
class Owner
{
public:
Owner()
{
m_ptr = new(&m_storage) SomeClass();
}
~Owner()
{
m_ptr->~SomeClass();
}
private:
std::aligned_union<0, SomeClass> m_storage;
SomeClass* m_ptr;
};
Note: in this case, you are responsible to calling destructor of the object, as shown above.
You can wrap m_ptr
with a unique_ptr
(with a deleted which only calls a destructor) to avoid this:
struct DtorDeleter
{
template<typename T>
void operator ()(T* ptr) { ptr->~T(); }
};
std::unique_ptr<SomeClass, DtorDeleter> m_ptr; // no need to call destructor manually
Upvotes: 3
Reputation: 30020
You can use an union for this (C++11 needed):
#include <new>
class Foo {
public:
Foo(int a) { }
};
class Bar {
public:
Bar() {
new(&m_foo) Foo(42); // call the constructor
// you can use m_foo from this point
}
~Bar() {
m_foo.~Foo(); // call the destructor
}
private:
union { // anonymous union
Foo m_foo;
};
};
Note that you need to explicitly call the destructor of m_foo
at ~Bar()
.
Upvotes: 0
Reputation: 73444
No.
You cannot call the constructor of a member class outside the initializer list.
PS: Even if you don't call it yourself in the initializer list, then the compiler will do it implicitly.
If you cannot call it in the initializer list, and you don't want to use an init-like method, then re-think your design/approach.
Upvotes: 5