Is there a way to tell gcc that the abstract class it's compiling does not need a virtual destructor (like COM-objects never have)? For example nsISupports always complains about the missing virtual destructor. Turning off the warning would not help as I may have non-COM-like classes, where I want this warning.
So __attribute__((com_interface)) is deprecated and changed only the vtable layout. Is there another __attribute__ where I can tell the compiler that I don't want to be warned about the missing destructor on this class?
The missing virtual dtor warning is there for a reason - mainly because it's a debugging nightmare to track down, especially in a large and complex code base
You may have a very specific reason for doing this but ask yourself, what happens if a class gets refactored such that it's usage changes later down the line?
I think you should re-consider disabling this warning. It's there for a reason. Not putting a virtual destructor in your class may be correct today, but you cannot predict exactly how your class will be used in the future.
A subtle change in the way the class is used could lead to the next developer pulling their hair out for hours trying to track down a resource leak. Do that person a favor and make the destructor virtual now.
Also you may want to ask yourself
What do I gain by making it non-virtual
You mentioned having an abstract class so I assume it has at least a single virtual function. So making the destructor virtual doesn't add a v-table to the object, it just merely extends it to include another member.
I can't see any real gain in making this non-virtual. Only problems.
You probably want to use a pair of diagnostic pragmas. Failing that, #pragma GCC system_header disables all warnings in a given file.
Related
The C++ core guidelines contain the following advice regarding the virtual, override and final specifiers, specifically relating to derived class destructors:
If a base class destructor is declared virtual, one should avoid declaring derived class destructors virtual or override. Some code base and tools might insist on override for destructors, but that is not the recommendation of these guidelines.
Sure enough, clang-tidy is one of those tools that goes against the recommendation.
If I do not specify either virtual or override, running clang-tidy emits the following warning:
warning: annotate this function with 'override' or (rarely) 'final' [modernize-use-override]
or, if specified just as virtual:
warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
My question
Given that specifying override, in particular, has the advantage of (at least) ensuing you have correctly specified the base class destructor as virtual, my question boils down to the following specific parts:
What, if any, are the arguments in favour of not specifying virtual or override on derived class destructors?
In your opinion, should I lean more towards the clang-tidy advice, or towards the C++ core guidelines advice?
What, if any, are the arguments in favour of not specifying ... override on derived class destructors?
There are non-conformant compilers that fail to compile when destructor is specified with override: https://msdn.microsoft.com/en-us/library/xfzxhe2a.aspx.
What, if any, are the arguments in favour of not specifying virtual ... on derived class destructors [when it is virtual implicitly]?
Less code is better. You save 7 characters worth by not using redundant virtual.
Counter argument: 7 characters is not much of a saving.
There might be a design decision to make a previously virtual destructor non-virtual for a base class and all of its children. If this guideline (of not specifying redundant virtual) is strictly followed, then only the base needs to be modified. Otherwise each child in the hierarchy must be modified (or at least checked whether they specify virtual separately).
Counter argument: This might be a completely hypothetical situation. Certainly quite rare.
In your opinion, should I lean more towards the clang-tidy advice, or towards the C++ core guidelines advice?
The only argument that has significant weight in my opinion is the non-conformance of old Visual Studio compilers, and thus I would err on the side of not using override on destructors. Otherwise it matters very little and you can follow whichever guideline you prefer, or don't even bother following either - consistency isn't important when the subject at hand makes no difference.
I have a class which may or may not be extended (inherited) by other parties.
So I declare every function which is "plausibly-inheritable" as virtual.
On my current application, however, this class is never inherited.
So it seems wasteful to do so, due to the overhead of reading the V-Table upon every function-call.
I've been trying to think of a way to optimize it when there is only one V-Table in the class hierarchy.
But it seems impossible, since the compiler cannot infer this vital piece of information.
So the only solution that comes to mind is with the preprocessor, but I doubt that there is one.
I'm pretty sure I'm not the first one to encounter this problem, so any suggestions will be appreciated...
UPDATE:
Perhaps I should just leave the header file without any virtual, and let other users add it if needed.
But it doesn't sound like the right way...
If you verified, that this is a bottleneck, then it might worth to do this small workaround:
#define omg_virtual
And later when you add more classes:
#define omg_virtual virtual
Or simply do a search-replace on the code base.
You should not make every method virtual. It should be a real design decision, and the tradeoff is a small performance hit against flexibility.
For your use case, it is very probable the compiler can infer your call to virtual method doesn't need a lookup to the vtable and will discard it by iself.
If I have this situation in C++ project:
1 base class 'Base' containing only pure virtual functions
1 class 'Derived', which is the only class which inherits (public) from 'Base'
Will the compiler generate a VTABLE?
It seems there would be no need because the project only contains 1 class to which a Base* pointer could possibly point (Derived), so this could be resolved compile time for all cases.
This is interesting if you want to do dependency injection for unit testing but don't want to incur the VTABLE lookup costs in production code.
I don't have hard data, but I have good reasons to say no, it won't turn virtual calls into static ones.
Usually, the compiler only sees a single compilation unit. It cannot know there's only a single subclass, because five months later you may write another subclass, compile it, get some ancient object files from the backup and link them all together.
While link-time optimizations do see the whole picture, they usually work on a far lower-level representation of the program. Such representation allow e.g. inlining of static calls, but don't represent inheritance information (except perhaps as optional metadata) and already have the virtual calls and vtables spelt out explicitly. I know this is the case for Clang and IIRC gcc's whole-program optimizations also work on some low-level IR (GIMPLE?).
Also note that with dynamic loading, you can still add more subclasses long after compilation and LTO. You may not need it, but if I was a compiler writer, I'd be weary of adding an optimization that allows people royally breaking virtual calls in very specific, hard-to-track-down circumstances.
It's rarely worth the trouble - if you don't need virtual calls (e.g. because you know you won't need any more subclasses), don't make stuff virtual. Review your design. If you need some polymorphism but not the full power of virtual, the curiously recurring template pattern may help.
The compiler doesn't have to use a vtable based implementation of virtual function dispatch at all so the answer to your question will be specific to the implementation that you are using.
The vtable is usually not only used for virtual functions, but it is also used to identify the class type when you do some dynamic_cast or when the program accesses the type_info for the class.
If the compiler detects that no virtual functions ever need a dynamic dispatch and none of the other features are used, it just could remove the vtable pointer as an optimization.
Obviously the compiler writer hasn't found it worth the trouble of doing this. Probably because it wouldn't be used very often.
Should be a newbie question...
I have existing code in an existing class, A, that I want to extend in order to override an existing method, A::f().
So now I want to create class B to override f(), since I don't want to just change A::f() because other code depends on it.
To do this, I need to change A::f() to a virtual method, I believe.
My question is besides allowing a method to be dynamically invoked (to use B's implementation and not A's) are there any other implications to making a method virtual? Am I breaking some kind of good programming practice? Will this affect any other code trying to use A::f()?
Please let me know.
Thanks,
jbu
edit: my question was more along the lines of is there anything wrong with making someone else's method virtual? even though you're not changing someone else's implementation, you're still having to go into someone's existing code and make changes to the declaration.
If you make the function virtual inside of the base class, anything that derives from it will also have it virtual.
Once virtual, if you create an instance of A, then it will still call A::f.
If you create an instance of B and store it in a pointer of type A*. And then you call A*::->f, then it will call B's B::f.
As for side effects, there probably won't be any side effects, other than a slight (unnoticeable) performance loss.
There is a very small side effect as well, there could be a class C that also derives from A, and it may implement C::f, and expect that if A*::->f was called, then it expects A::f to be called. But this is not very common.
But more than likely, if C exists, then it does not implement C::f at all, and in which case everything is fine.
Be careful though, if you are using an already compiled library and you are modifying it's header files, what you are expecting to work probably will not. You will need to recompile the header and source files.
You could consider doing the following to avoid side effects:
Create a type A2 that derives from A and make it's f virtual
Use pointers of type A2 instead of A
Derive B from type A2.
In this way anything that used A will work in the same way guaranteed
Depending on what you need you may also be able to use a has-a relationship instead of a is-a.
There is a small implied performance penalty of a vtable lookup every time a virtual function is called. If it were not virtual, function calls are direct, since the code location is known at compile time. Wheras at runtime, a virtual function address must be referenced from the vtable of the object you're calling upon.
To do this, I need to change A::f() to
a virtual method, I believe.
Nope, you do not need to change it to a virtual method in order to override it. However, if you are using polymorphism you need to, i.e. if you have a lot of different classes deriving from A but stored as pointers to A.
There's also a memory overhead for virtual functions because of the vtable (apart from what spoulson mentioned)
There are other ways of accomplishing your goal. Does it make sense for B to be an A? For example, it makes sense for a Cat to be an Animal, but not for a Cat to be a Dog. Perhaps both A and B should derive from a base class, if they are related.
Is there just common functionality you can factor out? It sounds to me like you'll never be using these classes polymorphically, and just want the functionality. I would suggest you take that common functionality out and then make your two separate classes.
As for cost, if you're using A ad B directly, the compile will by-pass any virtual dispatching and just go straight to the functions calls, as if they were never virtual. If you pass a B into a place expecting `A1 (as a reference or pointer), then it will have to dispatch.
There are 2 performance hits when speaking about virtual methods.
vtable dispatching, its nothing to really worry about
virtual functions are never inlined, this can be much worse than the previous one, function inlining is something that can really speed things in some situations, it can never happen with a virtual function.
How kosher it is to change somebody else's code depends entirely on the local mores and customs. It isn't something we can answer for you.
The next question is whether the class was designed to be inherited from. In many cases, classes are not, and changing them to be useful base classes, without changing other aspects, can be tricky. A non-base class is likely to have everything private except the public functions, so if you need to access more of the internals in B you'll have to make more modifications to A.
If you're going to use class B instead of class A, then you can just override the function without making it virtual. If you're going to create objects of class B and refer to them as pointers to A, then you do need to make f() virtual. You also should make the destructor virtual.
It is good programming practise to use virtual methods where they are deserved. Virtual methods have many implications as to how sensible your C++ Class is.
Without virtual functions you cannot create interfaces in C++. A interface is a class with all undefined virtual functions.
However sometimes using virtual methods is not good. It doesn't always make sense to use a virtual methods to change the functionality of an object, since it implies sub-classing. Often you can just change the functionality using function objects or function pointers.
As mentioned a virtual function creates a table which a running program will reference to check what function to use.
C++ has many gotchas which is why one needs to be very aware of what they want to do and what the best way of doing it is. There aren't as many ways of doing something as it seems when compared to runtime dynamic OO programming languages such as Java or C#. Some ways will be either outright wrong, or will eventually lead to undefined behavior as your code evolves.
Since you have asked a very good question :D, I suggest you buy Scott Myer's Book: Effective C++, and Bjarne Stroustrup's book: The C++ Programming Language. These will teach you the subtleties of OO in C++ particularly when to use what feature.
If thats the first virtual method the class is going to have, you're making it no longer a POD. This can break things, although the chances for that are slim.
POD: http://en.wikipedia.org/wiki/Plain_old_data_structures
This is probably habitual programming redundancy. I have noticed DECLSPEC_NOVTABLE ( __declspec(novtable) ) on a bunch of interfaces defined in headers:
struct DECLSPEC_NOVTABLE IStuff : public IObject
{
virtual method1 () = 0;
virtual method2 () = 0;
};
The MSDN article on this __declspec extended attribute says that adding this guy will remove the construct and desctructor vtable entries and thus result in "significant code size reduction" (because the vtable will be removed entirely).
This just doesn't make much sense to me. These guys are pure virtual, why wouldn't the compiler just do this by default?
The article also says that if you do this, and then try and instantiate one of these things, you will get a run time access violation. But when I tried this with a few compilers (with or without the __declspec extension), they don't compile (as I would have expected).
So I guess to summarize:
Does the compiler strip out the vtable regardless for pure virtual interfaces, or have I missed something fundamental here?
What is the MSDN article talking about ?
The compiler strips out the only reference to the vtable, which would have been during construction of the class. Therefore, the linker can optimize it away since there is no longer a reference in the code to it.
Also by the way, I have made a habit of declaring an empty constructor as protected, and also using Microsoft's extension abstract keyword, to avoid that access violation at runtime. This way, the compiler catches the problem at compile time instead (since only a base class can instantiate the interface through the protected constructor). The derived class will of course fill in the vtable during its construction.
It's a bit of handholding for a dumb compiler/linker. The compiler should not insert any reference to this vtable, as it is quite obvious that there is no need for this vtable. The compiler could also mark the reference in such a way that the linker can eliminate the vtable, but that's more complex of course.