My current situation is as follows. It is a more or less simple case of inheritance and I have multiple questions about it.
I have an abstract class (= it has pure virtual functions) with two variables foo_
and bar_
. foo_
is set by a parameter in the constructor. bar_
should default to 1000 for most subclasses, but I want one specific class to override it to 50000.
Here is a code snippet:
class Base {
protected:
const int foo_;
const int bar_;
public:
Base(int foo) : foo_{foo}, bar_{1000} {}
}
class Derived : public Base {}
First, one quick question: Is it better practice to initialize bar_
in the initialization list as I did in the example or do it at the top where the variable was declared as const int bar_{1000};
?
Second quick question: Is it ok to use {}
in initialization lists or should one use ()
?
How do I correctly write the constructor for the Derived class? I want to specifically call the constructor I defined for Base and also use an initalization list to set bar_
to 50000.
My idea was something like this:
Derived(int foo) : Base(foo), bar_{50000} {}
EDIT: After a bit of trying I noticed that modifying bar_ in Derived's constructor list is apparently not possible, because "bar_" is not a nonstatic data member or base class of class "Derived"
.
There are many aspects in this question to be tackled.
My preference for initialization goes to:
class Base {
protected:
const int foo_{};
const int bar_{1000};
public:
Base(int foo) : foo_{foo} {}
}
The reasons I prefer this is because a class can have multiple constructors. This makes it easier to maintain the defaults.
For the question about the initialization, I give up. Just use the styleguide that is out there. (Currently they seem to be standardized on using {} everywhere) Outside of constructors, it's even a bigger mess to initialize, if you want to be horrified by the details, I can recommend: Nicolai Josuttis "The Nightmare of Initialization in C++".
For writing the constructor in the derived class, I'd argue your member shouldn't be protected. If it would be private, the only way to write it is:
class Base {
private:
const int foo_{};
const int bar_{1'000};
protected:
Base(int foo, int bar) : foo_{foo}, bar_{bar} {}
public:
Base(int foo) : foo_{foo} {}
}
class Derived : public Base {
public:
Derived(int foo) : Base{foo, 50'000} {}
}
With this, I would expose the access to them via a protected method. Even ignoring that advice, I would use this technique to intialize it as it's the easiest to understand what could happen if you only look at the 'Base' class.