Is there any reason to specify a function as final when the class is already final? Or is that redundant?
class B
{
public:
virtual void f();
};
class D final : public B
{
public:
virtual void f() final; // Redundant final?
};
Would it be a good rule of thumb to say: Start with making the whole class final, and only switch to making individual functions final when you need to derive from the class and/or override specific functions?
It is definitely redundant because marking whole class as final makes it impossible to derive from this class and therefore override anything.
9 Classes [class]
If a class is marked with the class-virt-specifier final and it appears as a base-type-specifier in a base-clause
(Clause 10), the program is ill-formed.
So compiler won't even bother to check whether class deriving from final class actually tries to override anything or not.
No, it is not redundant, because final means different things when applied to classes and methods.
When final is applied to a class, it means that the class may not appear in the base-specifier-list of another class (i.e. you can't inherit from it)
When final is applied to a member function, it means that the function must be virtual in an ancestor class, and further specifies that it may not be overridden in a descendant class.
The key distinction is that final on a member function says that you must be overriding a virtual method in an ancestor class- if you're not, the compiler throws an error. When applied to a member function, final is basically an extension of the override keyword.
Applying final to methods can be very helpful in catching subtle bugs that would not be caught if you only specify final on the class.
Example 1: If you have misspelled the function name, or have not perfectly reproduced the parameter list, the function isn't actually overriding the base function and isn't going to be called when you think it's going to be called. But if you have specified that the function is final (or override) the compiler will detect that you are not successfully overriding a base function, and will throw an error. If you have only specified that the class is final, the compiler won't care that your function isn't actually overriding a virtual function, and won't throw an error.
Example 2: If you specify that a member function is final and the function signature in the base class changes (e.g. someone makes changes to the base class after you've tested and checked in your code), the compiler will helpfully point out that the base function is no longer being overridden by your function.
Related
I happened to be browsing the source for mongoDB, and found this interesting construct:
class NonspecificAssertionException final : public AssertionException {
public:
using AssertionException::AssertionException;
private:
void defineOnlyInFinalSubclassToPreventSlicing() final {}
};
How does the private method prevent slicing? I can't seem to think of the problem case.
Cheers, George
The only member functions to which the final specifier may be applied are virtual member functions. It is likely that in AssertionException or one of it's own base classes, this member is defined as
virtual void defineOnlyInFinalSubclassToPreventSlicing() = 0;
Thus, all classes in the hierarchy save the most derived ones are abstract base classes. One may not create values of abstract classes (they can only serve as bases). And so, one may not accidentally write
try {
foo();
}
catch(AssertionException const e) { // oops catching by value
}
If AssertionException was not abstract, the above could be written. But when it's abstract the compiler will complain at that exception handler, forcing us to catch by reference. And catching by reference is recommended practice.
Marking the member (and class) as final ensures no further derivation is possible. So the problem cannot reappear accidentally when the inheritance hierarchy is changed. Because a programmer that adds another class and again defines defineOnlyInFinalSubclassToPreventSlicing as final will elicit an error from the compiler, on account of this member already being declared final in the base. They will therefore have to remove the implementation from the base class, thus making it abstract again.
It's a bookkeeping system.
I'm getting a fatal linking error in the code below, it says:
]+0x10)||undefined reference to `base<node>::pass_derived(node)'|
I wanted to define a base class which has a pointer called poly_type and the base class can also "access" from within itself another class called derived. The problem I run into is line poly_type->pass_derived(n); where the compiler doesn't want to see the derived class where I tried to pass an object of type node. I'm guessing this is a limitation of C++, if so let me know. Heres the broken code,
edit seems like this has been asked somewhere else, I updated the source to reflect that opinion.
There is no definition of pass_derived in the base class.
You declare it as a virtual function but only define it in the derived class.
Because it instantiates base in the main function, the compiler tries to generate code for base but it does not find a definition for pass_derived.
You could add a default implementation - even if it is just empty.
As for whether you can eventually get it to call derived::pass_derived instead... :) good luck, it looks like fun. You are building your own version of inheritance?
The issue is here:
template < class T>
class base
{
// ...
virtual void pass_derived(T data);
};
You declared pass_derived as virtual but not pure virtual. Therefore, the linker raises an error if you don't provide an implementation.
Either you provide an implementation or (which I believe is your intent) you declare it pure virtual:
virtual void pass_derived(T data) = 0;
but then you cannot instantiate base<T> and must work only with pointers or references to base (which actually point/refer to derived).
This question already has answers here:
What's the point of a final virtual function?
(11 answers)
Closed 5 years ago.
In various explanations of C++11's final keyword, I'm seeing examples like this.
class base
{
public:
virtual void f() final;
};
class derived : public base
{
public:
virtual void f(); // Illegal due to base::f() declared final.
};
Is this actually a useful use of final? Why would you declare a virtual function in a base class (implying that it will be usefully overrideable in derived classes) and then immediately mark it as final (negating that implication)? What is the utility of virtual void f() final?
I can see the value of marking derived::f() final rather than base::f(). In this case, base::f() presumably had a good design-based reason for why f() should be virtual, and derived::f() separately has a good design-based reason for why no further-derived class should override its implementation.
If you don't want the function overridden polymorphically, why not just leave off the virtual keyword? Of course, derived classes might still override the function non-polymorphically. Is the purpose of virtual void f() final in the base class therefore to make base::f() firmly non-overrideable in any way—either as a virtual or non-virtual function? If so, then it seems a bit unfortunate that we must add the virtual keyword in this case only to enable use of final. I would think that it should then be legal to mark even non-virtual functions as final.
Why use virtual void f() final for a function originating in a base class when the sense of virtual and the sense of final seem to contradict?
Is there any sense in marking a base class function as both virtual and final?
Yes, at least temporarily.
I found myself in a relatively large and unfamiliar existing C++ source code base. Much of the code was written prior to C++11. I found that I wanted to ensure that all overrides of a virtual function in a base class were marked with override. The hard part is locating all of those overrides.
I marked the virtual function in the base class with final, and the compiler quickly showed me where every single override was declared. It was then very easy to decorate the overrides how I wanted, and remove the final from the virtual in the base class.
You can mark it virtual to indicate that it is 'virtual' in the class you are inheriting from (even though you don't have to do this), and mark it final to indicate that no class deriving from your class may override it further. This may happen when you are implementing an abstract base class, for example. This is C++11, so it's not useful; override is a much better indication, since it is enforced by the compiler.
Another possibility: you want this method not to be overridden, but you want to be able to change that without recompilation. Remember that virtual means it is in the virtual table. even if the compiler will not let you override it.
I think the purpose of the example you have shown is to demonstrate priorities between virtual and final, and nothing more. It is a minimal use of final, not a useful one.
Marking a non-virtual method as final makes no sense, since you cannot override them anyway. If you want the compiler to prevent hiding, that is a completely different issue, that has nothing to do with the method being final. In a sense, non-virtual methods are final already, but hidable.
The alternative is a non-virtual function. But non-virtual function can be hidden by a derived class. So if you want to prevent a function hiding, it can be specified as virtual final one.
I have an existing class that declares a virtual method and defines a default implementation. Now I want to overload that method with a differend parameter and also give a default implementation. Additionaly I want to enforce the constraint, that if the first method got overridden by a subclass then the second (overloaded) virtual method must be overridden too.
Is this even possible inside C++? If so, is it possible at compile time?
Example code:
class ParamA {};
class ParamB {};
class Base
{
public:
virtual void method(ParamA a)
{
// default behavior
}
virtual void method(ParamB b)
{
// default behavior
}
}
class Derived : public Base
{
public:
virutal void method(ParamA)
{
// special behavior
}
}
My goal is to detect classes of type Derived and enforce them to implement their verison of method(ParamB b).
No, you can't specify complex constraints on which sets of member functions must be overridden. The only constraints apply to individual functions; pure virtual (=0) to mandate overriding, and (in C++11) final to prevent overriding.
The best you can do is make both functions pure virtual, forcing the derived class to override both. This at least forces the author of the derived class to think about what needs overriding; it's impossible to override one and forget the other one.
You can still provide a default implementation, so that derived classes that don't want to override either function only need very short overrides that call the default versions.
I think C++ does not provide any means to detect such missing override in a child.
#larsmans: Making both methods pure virtuals leads to missing the default implementation.
#js_: could you elaborate a bit on your actual issue? What you are searching for seems to be conceptually not that clear to me.
How about creating a Parent class from which Base will inherit? These 2 functions will be pure virtual in the Parent class. The derived classes will inherit Parent (and not Base), and will have to implement both functions.
If you all you have to work with is the parent class, then no. It's not possible neither at compile time, nor as a runtime check.
Of course, you could introduce some macros (like say OVERRIDE_METHODS... I'm sure you see what I'm talking about), but nothing can prevent the users from ignoring them and override only one of said methods.
Plus such macros will make the code pretty ugly.
I have a question, here are two classes below:
class Base{
public:
virtual void toString(); // generic implementation
}
class Derive : public Base{
public:
( virtual ) void toString(); // specific implementation
}
The question is:
If I wanna subclass of class Derive perform polymophism using a pointer of type Base, is keyword virtual in the bracket necessary?
If the answer is no, what's the difference between member function toString of class Derive with and without virtual?
C++03 §10.3/2:
If a virtual member function vf is
declared in a class Base and in a
class Derived, derived directly or
indirectly from Base, a member
function vf with the same name and
same parameter list as Base::vf is
declared, then Derived::vf is also
virtual (whether or not it is so
declared) and it overrides
Base::vf.
That keyword there is strictly optional and makes no difference at all.
The virtual property is inherited from the base class and is assumed to be present even if you don't type it out.
The compiler already knows from the 'virtual' keyword in the base class that toString is a virtual method. No need to repeat it.
A function once a virtual always a virtual.
So in any event if the virtual keyword is not used in the subsequent classes, it does not prevent the function/method from being 'virtual' i.e. be overridden. So the following guideline might help from a team development point-of-view :-
If the function/method is supposed to
be overridden, always use the
'virtual' keyword. This is especially
true when used in interface / base
classes.
If the derived class is supposed to
be sub-classed further explicity
state the 'virtual' keyword for every
function/method that can be
overridden.
If the function/method in the derived
class is not supposed to be
sub-classed again, then the keyword
'virtual' is to be commented
indicating that the function/method
was overridden but there are no
further classes that override it
again. This ofcourse does not prevent
someone from overriding in the
derived class unless the class
is made final (non-derivable), but it
indicates that the method is not supposed to be
overridden.
Ex: /*virtual*/ void someFunc();
It doesn't matter to the compiler whether or not you supply the virtual keyword on derived versions of the function.
However, it's a good idea to supply it anyway, so that anyone looking at your code will be able to tell it's a virtual function.
It's a matter of good style, and the user-programmer knows what's going on. In C++0x you can use [[override]] to make it more explicit and visible. You can use [[base_check]] to force the usage of [[override]].
If you don't want or can't do that, simply use the virtual keyword.
If you derive without virtual toString, and you cast an instance of Derive back to Base, calling toString() would actually call Base's toString(), since as far as it know's that's an instance of Base.