Reputation: 1339
I have a class like below:
#pragma once
#include <atomic>
class MyClassAnother {
public:
MyClassAnother(int val) : m_val(val) {
}
private:
int m_val;
};
There is another class which holds an object to MyClassAnother
#pragma once
#include "MyClassAnother.hpp"
class MyClass {
public:
MyClass() {
}
void Func() {
anotherClassObject = MyClassAnother(2);
}
private:
MyClassAnother anotherClassObject;
};
And here is the main.cpp
#include "MyClass.hpp"
#include <iostream>
int main() {
MyClass object;
}
Of course the program does not compile. And its because of the following error
error: constructor for 'MyClass' must explicitly initialize the member 'anotherClassObject' which does not have a default constructor
Question:
But why? Why can't I delay initialise the class member? Is the workaround to have a default constructor and delay initialise it with the real constructor later? Is it an anti pattern to do it this way then?
I know that this can be resolved by making MyClassAnother anotherClassObject
a pointer. But I want to have MyClassAnother anotherClassObject
as a member object or a reference member in this case.
Upvotes: 0
Views: 273
Reputation: 181785
The constructor must guarantee that all members are properly constructed and initialized, and this one doesn't do that. What happens if you forget to call Func()
and then access objcect.anotherClassObject
?
Delayed initialization in general could be considered an anti-pattern, and goes against the RAII idiom, which states that object construction should succeed if and only if initialization of underlying resources (MyClassAnother
in this case) succeeded. It's a good pattern to follow, because it prevents having unusable objects around because they failed to initialize properly, or because somebody forgot to perform their delayed initialization steps.
If MyClass
objects are actually usable without a MyClassAnother
instance, you can wrap the latter in an std::unique_pointer
(C++11) or an std::optional
(C++17).
If MyClass
objects are not usable without a MyClassAnother
instance, you need to pass that instance to the constructor, or create it in the constructor's initializer list.
Upvotes: 1