Related
I got this question when I received a code review comment saying virtual functions need not be inline.
I thought inline virtual functions could come in handy in scenarios where functions are called on objects directly. But the counter-argument came to my mind is -- why would one want to define virtual and then use objects to call methods?
Is it best not to use inline virtual functions, since they're almost never expanded anyway?
Code snippet I used for analysis:
class Temp
{
public:
virtual ~Temp()
{
}
virtual void myVirtualFunction() const
{
cout<<"Temp::myVirtualFunction"<<endl;
}
};
class TempDerived : public Temp
{
public:
void myVirtualFunction() const
{
cout<<"TempDerived::myVirtualFunction"<<endl;
}
};
int main(void)
{
TempDerived aDerivedObj;
//Compiler thinks it's safe to expand the virtual functions
aDerivedObj.myVirtualFunction();
//type of object Temp points to is always known;
//does compiler still expand virtual functions?
//I doubt compiler would be this much intelligent!
Temp* pTemp = &aDerivedObj;
pTemp->myVirtualFunction();
return 0;
}
Virtual functions can be inlined sometimes. An excerpt from the excellent C++ faq:
"The only time an inline virtual call
can be inlined is when the compiler
knows the "exact class" of the object
which is the target of the virtual
function call. This can happen only
when the compiler has an actual object
rather than a pointer or reference to
an object. I.e., either with a local
object, a global/static object, or a
fully contained object inside a
composite."
C++11 has added final. This changes the accepted answer: it's no longer necessary to know the exact class of the object, it's sufficient to know the object has at least the class type in which the function was declared final:
class A {
virtual void foo();
};
class B : public A {
inline virtual void foo() final { }
};
class C : public B
{
};
void bar(B const& b) {
A const& a = b; // Allowed, every B is an A.
a.foo(); // Call to B::foo() can be inlined, even if b is actually a class C.
}
There is one category of virtual functions where it still makes sense to have them inline. Consider the following case:
class Base {
public:
inline virtual ~Base () { }
};
class Derived1 : public Base {
inline virtual ~Derived1 () { } // Implicitly calls Base::~Base ();
};
class Derived2 : public Derived1 {
inline virtual ~Derived2 () { } // Implicitly calls Derived1::~Derived1 ();
};
void foo (Base * base) {
delete base; // Virtual call
}
The call to delete 'base', will perform a virtual call to call correct derived class destructor, this call is not inlined. However because each destructor calls it's parent destructor (which in these cases are empty), the compiler can inline those calls, since they do not call the base class functions virtually.
The same principle exists for base class constructors or for any set of functions where the derived implementation also calls the base classes implementation.
I've seen compilers that don't emit any v-table if no non-inline function at all exists (and defined in one implementation file instead of a header then). They would throw errors like missing vtable-for-class-A or something similar, and you would be confused as hell, as i was.
Indeed, that's not conformant with the Standard, but it happens so consider putting at least one virtual function not in the header (if only the virtual destructor), so that the compiler could emit a vtable for the class at that place. I know it happens with some versions of gcc.
As someone mentioned, inline virtual functions can be a benefit sometimes, but of course most often you will use it when you do not know the dynamic type of the object, because that was the whole reason for virtual in the first place.
The compiler however can't completely ignore inline. It has other semantics apart from speeding up a function-call. The implicit inline for in-class definitions is the mechanism which allows you to put the definition into the header: Only inline functions can be defined multiple times throughout the whole program without a violation any rules. In the end, it behaves as you would have defined it only once in the whole program, even though you included the header multiple times into different files linked together.
Well, actually virtual functions can always be inlined, as long they're statically linked together: suppose we have an abstract class Base with a virtual function F and derived classes Derived1 and Derived2:
class Base {
virtual void F() = 0;
};
class Derived1 : public Base {
virtual void F();
};
class Derived2 : public Base {
virtual void F();
};
An hypotetical call b->F(); (with b of type Base*) is obviously virtual. But you (or the compiler...) could rewrite it like so (suppose typeof is a typeid-like function that returns a value that can be used in a switch)
switch (typeof(b)) {
case Derived1: b->Derived1::F(); break; // static, inlineable call
case Derived2: b->Derived2::F(); break; // static, inlineable call
case Base: assert(!"pure virtual function call!");
default: b->F(); break; // virtual call (dyn-loaded code)
}
while we still need RTTI for the typeof, the call can effectively be inlined by, basically, embedding the vtable inside the instruction stream and specializing the call for all the involved classes. This could be also generalized by specializing only a few classes (say, just Derived1):
switch (typeof(b)) {
case Derived1: b->Derived1::F(); break; // hot path
default: b->F(); break; // default virtual call, cold path
}
inline really doesn't do anything - it's a hint. The compiler might ignore it or it might inline a call event without inline if it sees the implementation and likes this idea. If code clarity is at stake the inline should be removed.
Marking a virtual method inline, helps in further optimizing virtual functions in following two cases:
Curiously recurring template pattern (http://www.codeproject.com/Tips/537606/Cplusplus-Prefer-Curiously-Recurring-Template-Patt)
Replacing virtual methods with templates (http://www.di.unipi.it/~nids/docs/templates_vs_inheritance.html)
Inlined declared Virtual functions are inlined when called through objects and ignored when called via pointer or references.
With modern compilers, it won't do any harm to inlibe them. Some ancient compiler/linker combos might have created multiple vtables, but I don't believe that is an issue anymore.
A compiler can only inline a function when the call can be resolved unambiguously at compile time.
Virtual functions, however are resolved at runtime, and so the compiler cannot inline the call, since at compile type the dynamic type (and therefore the function implementation to be called) cannot be determined.
In the cases where the function call is unambiguous and the function a suitable candidate for inlining, the compiler is smart enough to inline the code anyway.
The rest of the time "inline virtual" is a nonsense, and indeed some compilers won't compile that code.
It does make sense to make virtual functions and then call them on objects rather than references or pointers. Scott Meyer recommends, in his book "effective c++", to never redefine an inherited non-virtual function. That makes sense, because when you make a class with a non-virtual function and redefine the function in a derived class, you may be sure to use it correctly yourself, but you can't be sure others will use it correctly. Also, you may at a later date use it incorrectly yoruself. So, if you make a function in a base class and you want it to be redifinable, you should make it virtual. If it makes sense to make virtual functions and call them on objects, it also makes sense to inline them.
Actually in some cases adding "inline" to a virtual final override can make your code not compile so there is sometimes a difference (at least under VS2017s compiler)!
Actually I was doing a virtual inline final override function in VS2017 adding c++17 standard to compile and link and for some reason it failed when I am using two projects.
I had a test project and an implementation DLL that I am unit testing. In the test project I am having a "linker_includes.cpp" file that #include the *.cpp files from the other project that are needed. I know... I know I can set up msbuild to use the object files from the DLL, but please bear in mind that it is a microsoft specific solution while including the cpp files is unrelated to build-system and much more easier to version a cpp file than xml files and project settings and such...
What was interesting is that I was constantly getting linker error from the test project. Even if I added the definition of the missing functions by copy paste and not through include! So weird. The other project have built and there are no connection between the two other than marking a project reference so there is a build order to ensure both is always built...
I think it is some kind of bug in the compiler. I have no idea if it exists in the compiler shipped with VS2020, because I am using an older version because some SDK only works with that properly :-(
I just wanted to add that not only marking them as inline can mean something, but might even make your code not build in some rare circumstances! This is weird, yet good to know.
PS.: The code I am working on is computer graphics related so I prefer inlining and that is why I used both final and inline. I kept the final specifier to hope the release build is smart enough to build the DLL by inlining it even without me directly hinting so...
PS (Linux).: I expect the same does not happen in gcc or clang as I routinely used to do these kind of things. I am not sure where this issue comes from... I prefer doing c++ on Linux or at least with some gcc, but sometimes project is different in needs.
Say we have a library which provides a class
struct Base { int foo() { return 42; } };
I cannot change that class.
99% of the people never want to override foo, hence it has not been made virtual by the library designers.
But I need to override it:
struct MyClass : Base { int foo() { return 73; } };
Even worse, the library has interfaces accepting pointers to Base.
I want to plug in MyClass, but of course, since foo is not virtual, the code behind the interface always calls Base::foo. I want it to call MyClass::foo.
What can I do about it? Is there a common pattern to make Base::foo appear to be virtual?
In reality, Base::foo is QAbstractProxyModel::sourceModel.
I'm implementing a ProxyChain, to abstract many proxy models to a single one.
QAbstractProxyModel::setSourceModel is virtual, but QAbstractProxyModel::sourceModel isn't and that makes a lot of trouble.
void ProxyChain::setSourceModel(QAbstractItemModel* source_model)
{
for (auto* proxy : m_proxies) {
proxy->setSourceModel(source_model);
source_model = proxy;
}
QIdentityProxyModel::setSourceModel(source_model);
}
QAbstractItemModel* ProxyChain::sourceModel() const
{
return m_proxies.front()->sourceModel();
}
What can I do about it?
Nothing.
This is why guidelines tell us to use virtual if we want other people to be able to "pretend" that their classes are versions of our classes.
The author of Base did not do that, so you do not have that power.
That's it.
What can I do about it?
Nothing. If a member function is non-virtual, then it is non-virtual. This means that any code, anywhere in the code base, which takes a Base pointer or reference who calls base->foo will be calling exactly and only Base::foo. This call is statically (compile-time) bound to the function it calls.
You cannot reach into someone else's code and make them use dynamic binding. If they didn't choose to participate in dynamic binding, then you can't make them. You can create your own derived class and write your own version of foo which hides the base class version. But this will not affect the behavior of any code which gets a pointer/reference to Base.
In your specific case, your best bet will be to make sure to call the base class setSourceModel with the object that you want sourceModel to return any time something changes which changes what sourceModel should return.
I got this question when I received a code review comment saying virtual functions need not be inline.
I thought inline virtual functions could come in handy in scenarios where functions are called on objects directly. But the counter-argument came to my mind is -- why would one want to define virtual and then use objects to call methods?
Is it best not to use inline virtual functions, since they're almost never expanded anyway?
Code snippet I used for analysis:
class Temp
{
public:
virtual ~Temp()
{
}
virtual void myVirtualFunction() const
{
cout<<"Temp::myVirtualFunction"<<endl;
}
};
class TempDerived : public Temp
{
public:
void myVirtualFunction() const
{
cout<<"TempDerived::myVirtualFunction"<<endl;
}
};
int main(void)
{
TempDerived aDerivedObj;
//Compiler thinks it's safe to expand the virtual functions
aDerivedObj.myVirtualFunction();
//type of object Temp points to is always known;
//does compiler still expand virtual functions?
//I doubt compiler would be this much intelligent!
Temp* pTemp = &aDerivedObj;
pTemp->myVirtualFunction();
return 0;
}
Virtual functions can be inlined sometimes. An excerpt from the excellent C++ faq:
"The only time an inline virtual call
can be inlined is when the compiler
knows the "exact class" of the object
which is the target of the virtual
function call. This can happen only
when the compiler has an actual object
rather than a pointer or reference to
an object. I.e., either with a local
object, a global/static object, or a
fully contained object inside a
composite."
C++11 has added final. This changes the accepted answer: it's no longer necessary to know the exact class of the object, it's sufficient to know the object has at least the class type in which the function was declared final:
class A {
virtual void foo();
};
class B : public A {
inline virtual void foo() final { }
};
class C : public B
{
};
void bar(B const& b) {
A const& a = b; // Allowed, every B is an A.
a.foo(); // Call to B::foo() can be inlined, even if b is actually a class C.
}
There is one category of virtual functions where it still makes sense to have them inline. Consider the following case:
class Base {
public:
inline virtual ~Base () { }
};
class Derived1 : public Base {
inline virtual ~Derived1 () { } // Implicitly calls Base::~Base ();
};
class Derived2 : public Derived1 {
inline virtual ~Derived2 () { } // Implicitly calls Derived1::~Derived1 ();
};
void foo (Base * base) {
delete base; // Virtual call
}
The call to delete 'base', will perform a virtual call to call correct derived class destructor, this call is not inlined. However because each destructor calls it's parent destructor (which in these cases are empty), the compiler can inline those calls, since they do not call the base class functions virtually.
The same principle exists for base class constructors or for any set of functions where the derived implementation also calls the base classes implementation.
I've seen compilers that don't emit any v-table if no non-inline function at all exists (and defined in one implementation file instead of a header then). They would throw errors like missing vtable-for-class-A or something similar, and you would be confused as hell, as i was.
Indeed, that's not conformant with the Standard, but it happens so consider putting at least one virtual function not in the header (if only the virtual destructor), so that the compiler could emit a vtable for the class at that place. I know it happens with some versions of gcc.
As someone mentioned, inline virtual functions can be a benefit sometimes, but of course most often you will use it when you do not know the dynamic type of the object, because that was the whole reason for virtual in the first place.
The compiler however can't completely ignore inline. It has other semantics apart from speeding up a function-call. The implicit inline for in-class definitions is the mechanism which allows you to put the definition into the header: Only inline functions can be defined multiple times throughout the whole program without a violation any rules. In the end, it behaves as you would have defined it only once in the whole program, even though you included the header multiple times into different files linked together.
Well, actually virtual functions can always be inlined, as long they're statically linked together: suppose we have an abstract class Base with a virtual function F and derived classes Derived1 and Derived2:
class Base {
virtual void F() = 0;
};
class Derived1 : public Base {
virtual void F();
};
class Derived2 : public Base {
virtual void F();
};
An hypotetical call b->F(); (with b of type Base*) is obviously virtual. But you (or the compiler...) could rewrite it like so (suppose typeof is a typeid-like function that returns a value that can be used in a switch)
switch (typeof(b)) {
case Derived1: b->Derived1::F(); break; // static, inlineable call
case Derived2: b->Derived2::F(); break; // static, inlineable call
case Base: assert(!"pure virtual function call!");
default: b->F(); break; // virtual call (dyn-loaded code)
}
while we still need RTTI for the typeof, the call can effectively be inlined by, basically, embedding the vtable inside the instruction stream and specializing the call for all the involved classes. This could be also generalized by specializing only a few classes (say, just Derived1):
switch (typeof(b)) {
case Derived1: b->Derived1::F(); break; // hot path
default: b->F(); break; // default virtual call, cold path
}
inline really doesn't do anything - it's a hint. The compiler might ignore it or it might inline a call event without inline if it sees the implementation and likes this idea. If code clarity is at stake the inline should be removed.
Marking a virtual method inline, helps in further optimizing virtual functions in following two cases:
Curiously recurring template pattern (http://www.codeproject.com/Tips/537606/Cplusplus-Prefer-Curiously-Recurring-Template-Patt)
Replacing virtual methods with templates (http://www.di.unipi.it/~nids/docs/templates_vs_inheritance.html)
Inlined declared Virtual functions are inlined when called through objects and ignored when called via pointer or references.
With modern compilers, it won't do any harm to inlibe them. Some ancient compiler/linker combos might have created multiple vtables, but I don't believe that is an issue anymore.
A compiler can only inline a function when the call can be resolved unambiguously at compile time.
Virtual functions, however are resolved at runtime, and so the compiler cannot inline the call, since at compile type the dynamic type (and therefore the function implementation to be called) cannot be determined.
In the cases where the function call is unambiguous and the function a suitable candidate for inlining, the compiler is smart enough to inline the code anyway.
The rest of the time "inline virtual" is a nonsense, and indeed some compilers won't compile that code.
It does make sense to make virtual functions and then call them on objects rather than references or pointers. Scott Meyer recommends, in his book "effective c++", to never redefine an inherited non-virtual function. That makes sense, because when you make a class with a non-virtual function and redefine the function in a derived class, you may be sure to use it correctly yourself, but you can't be sure others will use it correctly. Also, you may at a later date use it incorrectly yoruself. So, if you make a function in a base class and you want it to be redifinable, you should make it virtual. If it makes sense to make virtual functions and call them on objects, it also makes sense to inline them.
Actually in some cases adding "inline" to a virtual final override can make your code not compile so there is sometimes a difference (at least under VS2017s compiler)!
Actually I was doing a virtual inline final override function in VS2017 adding c++17 standard to compile and link and for some reason it failed when I am using two projects.
I had a test project and an implementation DLL that I am unit testing. In the test project I am having a "linker_includes.cpp" file that #include the *.cpp files from the other project that are needed. I know... I know I can set up msbuild to use the object files from the DLL, but please bear in mind that it is a microsoft specific solution while including the cpp files is unrelated to build-system and much more easier to version a cpp file than xml files and project settings and such...
What was interesting is that I was constantly getting linker error from the test project. Even if I added the definition of the missing functions by copy paste and not through include! So weird. The other project have built and there are no connection between the two other than marking a project reference so there is a build order to ensure both is always built...
I think it is some kind of bug in the compiler. I have no idea if it exists in the compiler shipped with VS2020, because I am using an older version because some SDK only works with that properly :-(
I just wanted to add that not only marking them as inline can mean something, but might even make your code not build in some rare circumstances! This is weird, yet good to know.
PS.: The code I am working on is computer graphics related so I prefer inlining and that is why I used both final and inline. I kept the final specifier to hope the release build is smart enough to build the DLL by inlining it even without me directly hinting so...
PS (Linux).: I expect the same does not happen in gcc or clang as I routinely used to do these kind of things. I am not sure where this issue comes from... I prefer doing c++ on Linux or at least with some gcc, but sometimes project is different in needs.
I'm working on building Cppcheck on AIX with the xlC compiler (see previous question). Checker classes all derive from a Check class, whose constructor registers each object in a global list:
check.h
class Check {
public:
Check() {
instances().push_back(this);
instances().sort();
}
static std::list<Check *> &instances();
virtual std::string name() const = 0;
private:
bool operator<(const Check *other) const {
return (name() < other->name());
}
};
checkbufferoverrun.h
class CheckBufferOverrun: public Check {
public:
// ...
std::string name() const {
return "Bounds checking";
}
};
The problem I appear to be having is with the instances().sort() call. sort() will call Check::operator<() which calls Check::name() on each pointer in the static instances() list, but the Check instance that was just added to the list has not yet had its constructor fully run (because it's still inside Check::Check()). Therefore, it should be undefined behaviour to call ->name() on such a pointer before the CheckBufferOverrun constructor has completed.
Is this really undefined behaviour, or am I missing a subtlety here?
Note that I don't think the call to sort() is strictly required, but the effect is that Cppcheck runs all its checkers in a deterministic order. This only affects the output in the order in which errors are detected, which causes causes some test cases to fail because they're expecting the output in a particular order.
Update: The question as above still (mostly) stands. However, I think the real reason why the call to sort() in the constructor wasn't causing problems (ie. crashing by calling a pure virtual function) is that the Check::operator<(const Check *) is never actually called by sort()! Rather, sort() appears to compare the pointers instead. This happens in both g++ and xlC, indicating a problem with the Cppcheck code itself.
Yes, it's undefined. The standard specifically says so in 10.4/6
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
It is true that calling a pure virtual function from a constructor is always an undefined behaviour.
The virtual pointer can not be assumed to be set until the constructor has run completely (closing "}"), and hence any call to a virtual function (or pure virtual function) has to be setup at the time of compilation itself (statically bound call).
Now, if the virtual function is pure virtual function, the compiler will generally insert its own implementation for such pure virtual function, the default behavior of which is to generate a segmentation fault. The Standard does not dictate what should be the implementation of a pure virtual function, but most of C++ compilers adopt aforesaid style.
If your code is not causing any runtime mischief demeanour, then it is not getting called in the said call sequence. If you could post the implementation code for below 2 functions
instances().push_back(this);
instances().sort();
then maybe it will help to see what's going on.
As long as object construction isn't finished, a pure virtual function may not be called. However, if it's declared pure virtual in a base class A, then defined in B (derived from A), the constructor of C (derived from B) may call it, since B's construction is complete.
In your case, use a static constructor instead:
class check {
private Check () { ... }
public:
static Check* createInstance() {
Check* check = new Check();
instances().push_back(check);
instances().sort();
}
...
}
I think your real problem is that you've conflated two things: the Checker base class, and some mechanism for registering (derived) instances of Check.
Among other things, this isn't particularly robust: I may want to use your Checker classes, but I may want to register them differently.
Maybe you could do something like this: Checker get a protected ctor (it's abstract anyway, and so only derived classes ought to be calling the Checker ctor).
Derived classes also have protected ctors, and a public static method (the "named constructor pattern") to create instances. That creating method news up a Checker subclass, and them passes it (fully created at this point) to a CheckerRegister class (which is also abstract, so users can implemented their own if need be).
You use whatever singleton pattern, or dependency injection mechanism, that you prefer, to instantiate a Checkerregister and make it available to Checker subclasses.
One simple way to do this would be to have a getCheckerRegister static method on Checker.
So a Checker subclass might look like this:
class CheckBufferOverrun: public Check {
protected:
CheckBufferOverrun : Check("Bounds checking") {
// since every derived has a name, why not just pass it as an arg?
}
public:
CheckBufferOverrun makeCheckBufferOverrun() {
CheckBufferOverrun that = new CheckBufferOverrun();
// get the singleton, pass it something fully constructed
Checker.getCheckerRegister.register(that) ;
return that;
}
If it looks like this will end up being a lot of boilerplate code, write a template. If you worry that because each template instance in C++ is a real and unique class, write a non-templated base class that will register any Checker-derived.
I'm extending a class provided by a third part library. The class, let's call it Foo, has a reset() method which can be called in order to restart Foo's behavior. The reset() method is also used internally by the class.
class Foo
{
public:
void reset () {
/* ... */
}
void something () {
reset();
}
};
So far, I need to overload the reset() method in order to reset my additional features as well:
class Bar : public Foo
{
public:
void reset() {
/* ...something... */
Foo::reset();
}
};
Unfortunately, since the Foo::reset() method is not virtual, by calling Bar::something() I get the Foo::reset() method called instead of Bar::reset().
Is there a way (different from overloading Foo::something() as well) to make it backward-virtual?
You cannot extend classes that were not intended to be extended.
You can't make reset() virtual in your library in such a way that it will affect the base class without changing the base class's code. For starters, the compiler has not added the necessary bookkeeping code that allows it to make virtual calls to reset().
There is no 'clean way' of doing it using inheritance. Virtual is a compile/link time difference: using a vtable to resolve method at runtime (virtual) vs direct linking (non-virtual).
No this is not possible. The virtualness of a method is decided when the method is declared and you cannot change it later in a base class.
To allow you to do so would be nothing short of a disaster. Virtual methods simply behave differently than non-virtual methods and it must be accounted for when designing an object. With this proposal I would have to consider that all of my methods could behave in 2 distinctly different ways. That significantly adds to the design cost of the application and reduces the reliability.
If neither reset nor something are virtual, you're screwed, and that's the end of the story. If something is virtual you could override it. However, if these necessary methods aren't virtual, then the class isn't intended to be extended (or implemented properly, if it was intended).
Edit:
You COULD try composition, e.g.
class Bar {
Foo f;
// foo's methods, etc, wrapped here
void something() {
f.reset();
reset();
}
};
But if you need the whole, implicit conversion, thing, you're still stuffed.