C++ forbid overwriting a virtual function
Asked Answered
S

3

8

I use a class A from a library and want to add some functionality to it via an own class B. The user of class B should derive from it as if he would derive from class A.

class A {
    public:
        virtual void func1()=0;
        virtual void func2()=0;
        ...
}
class B: public A {
    public:
        virtual void func1() {...}
}

So if someone creates a class C deriving from B, he should have to implement func2:

class C: public B {
    public:
        virtual void func2() {...}
}

It is very important for my application, that class C doesn't overwrite func1, eliminating B::func1().

Is there a way to forbid overwriting this virtual function for all child classes of B? If not in plain C++, is there something in boost MPL that throws a compiler error, when this function is overwritten?

Spain answered 24/8, 2011 at 14:42 Comment(12)
Is there ever a case where a subclass of A should override func2 and if not, why is it virtual?Farica
Don't think that that's possible. Since when new C'ing a new ponter the compiler would try to set it to function in the most-derived class. Stopping in the middle of the derive-chain would break the intent of virtual functions.Spoiler
Simply put it in a private section in B? Unless I overlooked anything this could work.Agnosia
I assume you mean override, rather than overwrite? Why is it important to you that B::func1 is not overridden?Rheum
I'm not sure but possibly achievable with access specifiers and declaring these functions as protected.Trippet
Can you please elaborate on why it is so important? I see many people asking for this, but never seen a usecase where this is not a protection against maciavelli case.Medrek
gotw.ca/publications/mill18.htmNeap
GCC adds the new final keyword in 4.7.Vinnievinnitsa
@dark_charlie, Rolice: public/private is only an access specifier and determines who can call the function. It has nothing to do with virtual functions overriding. Private virtual functions can be overridden in child classes.Spain
@PlasmaHH: I derive a class from CDialogImpl to implement a parent class for specific windows. These windows need to do some handling in the OnFinalMessage() (eg delete themselves). When someone inherits from this parent class, he should not be able to override OnFinalMessage, because this would cause some ugly memory leaks.Spain
@Heinzi: what harm would be done if you document this issue and have those that override the function call always call your function too? This should be flexible enough to provide the ability to add behaviour by overriding, but also save you. since you documented it, it is their fault if something goes wrong. it doesnt sound like a good idea to make it impossible to use a class wrong (murphy vs. machiavelli)Medrek
I'm a proponent of another policy. I think it's better to throw compiler errors or compiler warnings if a class is used in a wrong way. Documentation can easily be ignored. To preserve flexibility, I offer another virtual function that can be overridden and is called inside of my implementation of OnFinalMessage().Spain
C
7

No, that's not possible in the current edition of C++, aka C++03. The upcoming C++11 standard will include the contextual keyword final which will make this possible:

// C++11 only: indicates that the function cannot be overridden in a subclass
virtual void MemberFunction() final { ... }

The Microsoft Visual C++ compiler also includes the keyword sealed, as an extension, which functions similarly to the C++11 keyword final, but this only works with Microsoft's compiler.

Cupulate answered 24/8, 2011 at 14:50 Comment(4)
It's not really keyword, but rather a contextual keyword, right? That is, I can still use final as an identifier?Eastlake
sealed is not an Microsoft extension for C++, this keyword is a part of C++\CLI which, strictly speaking, is a separate language.Overwrite
@Kirill: Yes, it is. See the documentation I linked to: "sealed is also valid when compiling for native targets (without /clr)."Cupulate
@Adam Rosenfield, I see it now. Didn't know it can be used in native C++.Overwrite
B
7

Not in C++03, but C++0x provides the special "final" identifier to prohibit this:

http://en.wikipedia.org/wiki/C++0x#Explicit_overrides_and_final

Britneybritni answered 24/8, 2011 at 14:47 Comment(2)
Wasn't this originally done by Java? (My god, I've found something about Java I actually like!)Epimorphosis
@Epimorphosis I don't know about "originally", but the first thing I thought of when I saw it was - "Oh - just like Java!" (so you're in good company ;))Britneybritni
C
7

No, that's not possible in the current edition of C++, aka C++03. The upcoming C++11 standard will include the contextual keyword final which will make this possible:

// C++11 only: indicates that the function cannot be overridden in a subclass
virtual void MemberFunction() final { ... }

The Microsoft Visual C++ compiler also includes the keyword sealed, as an extension, which functions similarly to the C++11 keyword final, but this only works with Microsoft's compiler.

Cupulate answered 24/8, 2011 at 14:50 Comment(4)
It's not really keyword, but rather a contextual keyword, right? That is, I can still use final as an identifier?Eastlake
sealed is not an Microsoft extension for C++, this keyword is a part of C++\CLI which, strictly speaking, is a separate language.Overwrite
@Kirill: Yes, it is. See the documentation I linked to: "sealed is also valid when compiling for native targets (without /clr)."Cupulate
@Adam Rosenfield, I see it now. Didn't know it can be used in native C++.Overwrite
I
4

No. In C++03, you cannot stop derived classes from overriding1 virtual function(s) of base classes. However, base classes can force the derived (non-abstract) classes to provide implementation for virtual functions (in which case, the virtual functions are actually pure virtual functions).

1. The correct terminology is override, not overwrite.

Innominate answered 24/8, 2011 at 14:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.