I have an abstract C++ class with no constructor. It's supposed to be a base class so other classes can inherit from it. What I am trying to do is to declare a constant variable in the base class and initialize it in each derived class' constructor but nowhere else in each one of those classes. Is it legal in C++? If so, how can I do that?
Asked
Active
Viewed 1.5k times
3 Answers
23
Is it legal in C++?
No. The constant must be initialized in the base class constructor.
The solution is to provide an appropriate constructor in your base class – otherwise it cannot be used. Furthermore, there’s no reason not to provide that constructor.
class Base {
int const constant;
public:
virtual ~Base() = 0; // Makes this an abstract base class.
protected:
Base(int c) : constant(c) { }
};
// Must be implemented!
Base::~Base() { }
class Derived : public Base {
public:
Derived() : Base(42) { }
};

Konrad Rudolph
- 530,221
- 131
- 937
- 1,214
-
If you make the base class constructor `protected` then you don't have to worry about anyone else instantiating it directly. – Zooba Oct 11 '10 at 08:56
-
I thought if there is a constructor in an abstract base class, it is no longer abstract anymore because it can be instantiated. Am I wrong? – user246392 Oct 11 '10 at 08:57
-
@Zooba: Correct. See my updated code. ;-) Additionally, there are other ways to make a base class abstract (i.e. uninstantiable). The standard way is to provide a pure virtual function (e.g. conveniently the destructor, which **must** be virtual anyway). – Konrad Rudolph Oct 11 '10 at 08:57
-
@user246392: Yes you are wrong. Look at my code: the constructor is protected, so the class cannot be instantiated directly. What’s more, there is a pure virtual function so even with a public constructor, the class can’t be constructed by itself. – Konrad Rudolph Oct 11 '10 at 08:58
-
3+1, yep yep. Note that if you're going to implement `Base::~Base` in the header file, it should be `inline virtual`. – Potatoswatter Oct 11 '10 at 09:03
-
@Potatoswatter Does it need to be explicitly marked as inline? – Pedro d'Aquino Oct 11 '10 at 12:49
-
@Pedro: Any function defined in a header must be inline per the one-definition rule. (Or in an anonymous namespace.) This function won't be inline unless explicitly marked, so yes. – Potatoswatter Oct 11 '10 at 16:59
-
@Potatoswatter The `inline` declaration is only a guide to the compiler. Without it, you may get one definition per #include, or the compiler may inline it and give you one definition per use. Either way, with an empty method block, there are no ill-effects. (Hopefully the compiler will optimise the call out completely.) – Zooba Oct 11 '10 at 21:21
-
@Zooba: No, `inline` is required. It is not a performance hint; it changes the meaning of the declaration. The function body being empty does not change anything. http://stackoverflow.com/questions/1875947/benefits-of-declaring-a-function-as-inline – Potatoswatter Oct 11 '10 at 21:25
-
@Potatoswatter True. I didn't realise the consequences of the implicit `inline` when providing an implementation within the class definition. However, since no diagnostic is required (quotes @ http://stackoverflow.com/questions/908830#910686), the end result will likely be as I described, even if "exactly one" is violated, but there would be no ill effects since the method doesn't do anything. – Zooba Oct 11 '10 at 21:40
-
@Zooba: Since a destructor doesn't have a name, its address may not be taken, so I suppose that's pretty much true. For a named inline pure virtual function, though, taking its address in two different source files should produce a multiple definitions linker error. (Unless the linker is friendly enough to merge the identical definitions, which is really a mixed blessing.) – Potatoswatter Oct 11 '10 at 22:33
-
@Zooba: It’s not only a problem of diagnostics. The linker won’t know what to do with the multiple definitions of the same symbol. What is it supposed to do? It doesn’t necessarily know that they really refer to the same method, so silently suppressing one of the definitions may be really dangerous. So it complains. – Konrad Rudolph Oct 12 '10 at 06:25
-
@Konrad Okay, so I did what I should've done in the first place and tested it... error LNK2005 (in VC10) for "already defined" which marking it `inline` fixes. Looks like I learned an important use for `inline` along with some humility at the same time. (Gotta respect the efficiency of that, I guess...) – Zooba Oct 13 '10 at 06:38
-
@KonradRudolph kudos, this was awesome. – Yogesh May 30 '19 at 07:49
-
I wish this worked with delegating constructors, i.e. if you already had a `Base(...)` with lots of arguments that did some initialization, and you wanted to add a protected `Base(int c, ...)` to set `constant` and then delegate to `Base(...)` for the rest of the arguments. – tomocafe Jul 12 '22 at 22:16
1
If at all you need to do it this way:
struct Base {
Base( std::string const & someValue )
: const_value( someValue ) {
}
protected:
std::string const const_value;
};
struct Derived : Base {
Derived()
: Base("Derived"){
}
};
The reason for this is that you are only allowed to assign values to a const value at initialization time. Once Base is initialized you are no longer allowed to modify the value. Therefore you have to do it that way as shown above.

Vinzenz
- 2,749
- 17
- 23
0
Why don't you make a protected constructor in the abstract base class and set the constant value there?

ur.
- 2,890
- 1
- 18
- 21