+ 7
[C++] Base and Derived classes constructor problem
I was doing another (private...) project and got stuck with an error. I have no idea what is that problem supposed to be. I made a simplified and generalized version of this part of code: https://code.sololearn.com/c4XqlKEu9F2b/?ref=app Can you, please, explain me: - Why does this error happen? - How to solve this error and prevent it in future?
15 ответов
+ 12
The error happens because, as you might remember, the base class constructor is called before the derived class constructor upon instantiation of a derived object. If you don't do so explicitly via the member initialization list, the compiler will try to call the default base constructor.
However, your base class only has a parameterized constructor, thus the compiler can not select a default constructor and construction fails.
Depending on what you want, you basically have two options:
1) Add a default constructor to your base class, e.g.
Base() = default;
2) Explicitly call a base constructor from the derived constructors, e.g. for the copy constructor
Derived( const Derived& other )
: Base{ other.value }
{}
+ 8
Ipang
I don't quite understand your issue, sorry.
Everything I stated above also goes for the copy constructor, i.e. first the base part is constructed via a base class constructor and then the derived part via the actual derived constructor.
Normally, the compiler automatically calls the default constructor if no explicit call is made from the member initialization list. However, "Base" has no default constructor (implicitly deleted), and the compiler can't figure out what to do on its own.
Therefore, if you don't add a default constructor, you need to explicitly call another constructor.
Actually, you could also call the base copy constructor:
Derived( const Derived& other )
: Base{ static_cast< const Base& >( other ) }
{}
+ 7
Ipang
The colon is just syntax for the member initialization list. This one:
https://en.cppreference.com/w/cpp/language/constructor
And instead of initializing a variable located in your derived class, you initialize the base class.
In fact, if you don't call a base constructor explicitly like that, the following two are equivalent
Derived( const Derived& other )
{
this->value = other.value;
}
Derived( const Derived& other )
: Base()
{
this->value = other.value;
}
due to the way how instances are constructed, which also was the root of the original problem - there was no Base::Base() in the "Base" class the compiler could have called.
But that does not mean any "Derived" constructor would return a "Base" instance, it's just part of the initialization process. At the end, you will get a "Derived" instance, which is what a constructor does, after all - it constructs an instance of its class.
+ 6
This works :
https://code.sololearn.com/cDd5xc8gem2U/?ref=app
+ 6
get
Yeah, I remember the SL tutorial only touches on the initialization of variables this way.
Well, I assume you mean declaration and definition. In that case, the list is part of the definition:
struct Derived
{
Derived( const Derived& );
...
};
Derived::Derived( const Derived& other )
: Base{ other.value }
{}
A declaration usually only contains necessary identifiers, types, and attributes like const, no other 'actual' code.
Ipang
Sorry, I always think of you as an experienced C++ user, so I was a bit surprised when you asked. Therefore, my explanation might have been off in that way.
As I said earlier, it's really very similar to variable initialization, only for those properties that are inherited. Assume for a second those properties were private - you would still want a way to initialize them from the derived class, and this is how you would do it.
Anyway, I'm sure you'll be able to grasp it quickly after some sleep - maybe try writing a code yourself or look more into it on the web.
+ 5
Shadow, thanks again, now have better understanding of colon and code between it and opening brace in the method definition than Sololearn C++ course explains! 😂
One more question: what about using this stuff when references and later full definitions are used? Are those colon and the code after it supposed to be in the reference or in the full definition (like with class inheritance)? (sorry that I write it not in the separate question, but I can make one)
+ 4
Shadow
First, Thank you for answering,
I remember member initializer from the tutorial here. But this is the first time I see it used this way. I thought member initializer were meant to initialize members of the Derived class itself, rather than its base class (Base).
I'm trying to grasp on it but now I'm a bit tired, and it looks hard to digest. I guess I have to read that again later maybe after sleep time.
+ 4
get
Apology for the noises. I meant not to hijack your thread, just couldn't help the curiosity and confusion (still).
Nice discussion topic BTW 👍
+ 4
Shadow
I don't know if I should be proud or ashamed you thought of me as "experienced" LOL 😆
I hope you wouldn't mind me asking you more surprising questions in future, cause that, is very possible hehehe
Yea I hope so too, but you know, most stuffs on the web don't go much into details, though I can live with that. I'd probably better off try to experiment on CPg later
Thanks Shadow 🙏
+ 4
Ipang just be proud, lol.
+ 4
Ipang you have nothing to be embarrassed about 😁
+ 3
Shadow
The colon here, what does it mean?
: Base{ other.value }
: Base { ( static_cast< const Base& > other ) }
{}
As I understand it, `Base( const Base& other )` return a `Base` instance? then does it mean `Derived( const Derived& other )` also return a `Base` instance?
I'm just confused, sorry if my confirmation was unclear. I'm just wanting to understand.
+ 3
Sonic
Now I'm really embarrassed LMAO 😂😂😂
+ 3
Sonic
Idk, but OOP is pretty hard subject for me TBH
I need to fix myself on that somehow 😁
+ 2
Shadow
I don't understand option 2)
Why we call `Base` copy constructor in the `Derived` copy constructor?