Virtual call from base in virtual inheritance - c++

I'm having a problem making a a virtual call when using virtual inheritance.
Below is sample compilable code that demonstrates a code which works when there is no virtual inheritance used, and also code which will fail on runtime when virtual inheritance is used.
BASE CLASSES
Here are base calsses for both cases:
#include <iostream>
class Base
{
public:
Base() { }
virtual ~Base() { }
// we need to make this bad call a good one!
virtual void bad_call(void* ptr)
{
Base* pThis = static_cast<Base*>(ptr);
pThis->f();
}
protected:
virtual void f() { std::cout << x << std::endl; }
int x = 0;
};
class Midle1 :
virtual public Base
{
public:
Midle1() { }
~Midle1() override { }
};
class Midle2 :
virtual public Base
{
public:
Midle2() { }
~Midle2() override { }
};
CASE 1 GOOD
Here is a case which makes no use of virtual inheritance (just normal inheritance), where both bad_call and good_call virtual functions work:
class GoodDerived :
public Base
{
public:
GoodDerived()
{
}
~GoodDerived() override
{
}
void good_call(void* ptr)
{
GoodDerived* pThis = static_cast<GoodDerived*>(ptr);
pThis->f();
}
void f() override
{
++x;
std::cout << x << std::endl;
}
};
int main()
{
GoodDerived good_derived;
good_derived.good_call(&good_derived); // OK, will print 1
good_derived.bad_call(&good_derived); // OK, will print 2
std::cin.get();
return 0;
}
CASE 2 BAD
And here is a case which will make use of virtual inheritance, the good_call function will succeed, but bad_call one will fail with "access violation reading location"
class BadDerived :
public Midle1,
public Midle2
{
public:
BadDerived() { }
~BadDerived() override { }
void good_call(void* ptr)
{
BadDerived* pThis = static_cast<BadDerived*>(ptr);
pThis->f();
}
void f() override
{
++x;
std::cout << x << std::endl;
}
};
int main()
{
BadDerived bad_derived;
bad_derived.good_call(&bad_derived); // OK, will print 1
bad_derived.bad_call(&bad_derived); // ERROR: causes access violation
std::cin.get();
return 0;
}
QUESTION
This second case is a simple code that demonstrated the issue I'm having right now in my project, and I need assistance on how to solve this, why is virtual inheritance causing troubles?
Why first case works just fine but second one does not?

The basic problem is that you're casting a pointer to void * and then casting it to a different pointer type. That doesn't work in general -- after casting a pointer to void *, the only useful thing you can do with it is cast it back to the EXACT SAME POINTER TYPE. If you want to cast to any other pointer type (reliably) you need to first cast back to the same original type.
I need assistance on how to solve this
Don't use void * here -- void * is a C solution that should never be used in C++. Change your virtual bad_call method to take a Base * as an argument not a void *. Then everything 'just works' and you don't need any of the static_casts at all. If you need to override bad_call in your Dervied class, it also needs to take a Base * argument, so you'll need to use dynamic_cast<Derived *>(ptr) there to get back the original Derived *, but that's not a big deal -- that's precisely what dynamic_cast exists for.

Make your call:
bad_derived.bad_call(static_cast<Base*>(&bad_derived));
You want to point to the Base part of the object but when using virtual inheritance there is no guarantee about where that will be located.

Let's decompose this, step by step.
&bad_derived: A pointer to BadDerived with pointer value pointing to an object with type BadDervived.
bad_derived.bad_call(&bad_derived): Implicitly converts &bad_derived to a pointer to void* with pointer value pointing to an object with type BadDervived.
Base* pThis = static_cast<Base*>(ptr);: Cast from a void* to Base*. Note that ptr has pointer value pointing to an object with type BadDervived, but BadDerived is not pointer-interconvertable with Base, thus pThis has type Base* but has pointer value pointing to an object with type BadDervived.
pThis->f();: Access the value of a BadDerived object using a glvalue (here a dereferenced pointer) of type Base, violates the strict-aliasing-rule. Undefined Behaviour.

I want to share a solution that makes this design possible (with the help of other answers and comments).
All the code remains same except adding a templated static mehtod to base class which will deduce void to correct type:
Here is modified Base class with helper template static function:
added a comment about CALLBACK also.
class Base
{
public:
Base() { }
virtual ~Base() { }
// this is example CALLBACK from Window API but templated
// The callback is registered with Windows in RegisterClassEx btw.
template<typename DERIVED_CLASS>
static void make_call(void* ptr)
{
DERIVED_CLASS* pThis = static_cast<DERIVED_CLASS*>(ptr);
pThis->bad_call(static_cast<Base*>(pThis));
}
// we need to make this bad call a good one!
virtual void bad_call(void* ptr)
{
Base* pThis = static_cast<Base*>(ptr);
pThis->f();
}
protected:
virtual void f() { std::cout << x << std::endl; }
int x = 0;
};
And here is how we invoke bad_call problematic function:
int main()
{
BadDerived bad_derived;
bad_derived.good_call(&bad_derived); // OK, will print 1
// HACA!!!
bad_derived.make_call<BadDerived>(&bad_derived); // OK will print 2
std::cin.get();
return 0;
}
This why I like C++ so much, everything is possible...

Related

How can a subclass be safely converted to a parent class in c++?

There is a subclass that inherits from a normal superclass and a superclass with a virtual function.When I convert subclass pointer to normal superclass pointer,it will work correctly.But when I use a another superclass pointer to point subclass, then convert pointer to this normal superclass, it will print a wrong answer.
#include <iostream>
using namespace std;
class base{
public:
virtual bool test1() = 0;
};
class base2{
public:
int a;
base2(int p) : a(p) {}
};
class son:public base, public base2 {
public:
bool test1() {
return true;
}
son(int p) : base2(p) {}
};
void out(base2* p) {
cout << p -> a;
}
int main()
{
/* if I use this, it will print a wrong number,such as -1359748056
base * o = new son(9);
out((base2*)o);
*/
/* if I use this, it will print 9
out(new son(9));
*/
return 0;
}
I dont't know Why.Converting a subclass to a parent class isn't safe?
What you wrote in the line
out((base2*)o);
is called a C-style cast or a reinterpret_cast. You should almost never do that when dealing with classes and object because it just changes the type of the pointer without taking care of adjusting the virtual table locations. For that reason it prints garbage, because it is looking at the wrong field offset.
Ideally you should use static cast as in
out( static_cast<base2*>(o) );
However base and base2 are not directly related by inheritance so static_cast throws out a compiler error. So you have to use the slower version dynamic cast as
out( dynamic_cast<base2*>(o) );
When you write this way, the program prints
Program stdout
99
Compiler Explorer

Can a base class know if a derived class has overridden a virtual method?

The same question exists for C#, but does not apply to C++.
class Base
{
void dispatch()
{
if (newStyleHasBeenOverridden()) //how to find this out?
newStyle(42);
else
oldStyle(1, 2);
}
virtual void oldStyle(int, int) { throw "Implement me!"; }
virtual void newStyle(int) { throw "Implement me!"; }
}
class Derived:public Base
{
void newStyle(int) override
{
std::cout<<"Success!";
}
}
WARNING: This solution is not cross-platform in that it relies on a GCC extension and some undefined behavior.
GCC allows a syntax to grab the pointer to the function from the vtable of this by saying this->*&ClassName::functionName. It is probably not a good idea to actually use this, but here's a demo anyway:
#include <iostream>
class Base {
public:
void foo() {
auto base_bar_addr = reinterpret_cast<void*>(&Base::bar);
auto this_bar_addr = reinterpret_cast<void*>(this->*&Base::bar);
std::cout << (base_bar_addr == this_bar_addr ? "not overridden" : "overridden") << std::endl;
}
virtual void bar() { };
};
class Regular : public Base { };
class Overriding : public Base {
public:
virtual void bar() { };
};
int main() {
Regular r;
r.foo();
Overriding o;
o.foo();
}
And for posterity:
ICC allows the syntax, but it has a different meaning, which is the same as just saying &Base::bar, so you'll always think it isn't being overridden.
Clang and MSVC reject the code outright.
This is a design problem.
However, in the interest of answering the actual question, there are a couple ways you could accomplish this without a redesign (but really, you should redesign it).
One (terrible) option is to call the newstyle method and catch the exception that occurs if it's not overridden.
void dispatch() {
try {
newStyle(42);
} catch (const char *) {
oldStyle(1, 2);
}
}
If newStyle has been overridden, the override will be called. Otherwise, the base implementation will throw, which dispatch will catch and then fall back to oldStyle. This is an abuse of exceptions and it will perform poorly.
Another (slightly less terrible) approach is to make the base implementation of newStyle forward to oldStyle.
void dispatch() {
newStyle(42);
}
virtual void newStyle(int) { oldStyle(1, 2); }
virtual void oldStyle(int, int) { throw "implement me"; }
This at least moves in the direction of a better design. The point of inheritance is to allow high level code to be able to use objects interchangeably, regardless of their specialization. If dispatch has to inspect the actual object type, then you've violated the Liskov Substitution Principle. Dispatch should be able to treat all the objects the same way, and any differences in behavior should arise from the overridden methods themselves (rather than the existence of overrides).
Making things simpler, the dispatch decision is done by the Derived class. Abstract Base class is basically just an "interface" where the Derived class should implement all virtual functions.
The problem too sounded like an XY problem.
I thought this is what you want:
class Base // abstract class
{
virtual void oldStyle(int, int) = 0; // pure virtual functions
virtual void newStyle(int) = 0; // needs to be implemented
};
class Derived:public Base
{
public:
Derived(bool useNewStyle): _useNewStyle(useNewStyle) {}
void newStyle(int) { std::cout << "new style"; }
void oldStyle(int, int) { std::cout << "old style"; }
void dispatch()
{
if (_useNewStyle) {
newStyle(42);
return;
}
oldStyle(1, 2);
return;
}
private:
bool _useNewStyle = false;
};
Derived d(true); // use new style
d.dispatch(); // "new style"

Safe to use static casting for performance in a unique virtual int type() for each instance?

I have a dense hierarchy of polymorphic objects, each of which comes with a mandatory virtual int type() = 0 method, which is manually written for every object.
The "safe" processing of the tree using dynamic_cast has a significant overhead, and as I already have a virtual method which will return a unique integer for each different type, I think it is safe to use an unsafe static cast. But I might be overlooking something, for example in cases of multiple inheritance or something else which may cause a misalignment which may cause the static cast to "crash"?
The hierarchy is traversed on base class level by different contexts, each of which has a custom way of interpreting the data, so for each object there is switch (type) and "do according to type" where the casting takes place.
The type() virtual is declared in the "utmost-base-class", which is always first in the inheritance.
According to the standard 5.2.9/2 the static cast you intend to do is safe, under the condition that the base class in not a virtual base class, nor a base of a virtual base class.
Here the example provided in the standard:
struct B { };
struct D : public B { };
D d;
B &br = d;
static_cast<D&>(br); // produces lvalue to the original d object
// Note that this works because B is not a virtual base class
So unless you use multiple inheritance with virtual bases, it's ok.
But be carefull if you have somethink like:
struct B { };
struct D1 : public virtual B { };
struct D2 : public virtual B {};
struct E : D1, D2 {};
E e;
B *pb=&e; //
static_cast<E*>(pb); // ouch !!! This would not safe
D1 *pd1 = &e;
static_cast<E*>(pd1); // but this would be ok
You can replace the use of dynamic_cast with static_cast in your code as long as you make sure that conversion is actually doing the right thing. dynamic_cast involves some run-time overhead which is missing from static_cast.
However, I am not sure if there could be some implication of replacement in case of multiple/virtual base classes. I had encountered a scenario where I stored addresses returned by operator new and then on later checking it showed that address is not present.
//Get the address from new
void* operator new(size_t size);
//Store this address in list.
std::list<void*> rawAddresses;
//Function to check if address is present
isAddressPresent(void* address) <<< This vomitted error when I passed object of
<<< class which has virtual base.
Using static_cast in this way should be fine -- as long as you can guarantee that you're casting to the correct type. I would highly recommend a simple unit test which can verify that you don't have any type() collisions (eg, a copy-paste error could cause SubclassB to have the same type() id as SubclassA) -- just add all types to a map and check for collisions. Further, you can safe-ishly create helper functions which guarantee the correct type (depending on your usage pattern). Here's an example.
// g++ test.cpp --std=c++11
#include <iostream>
#include <cassert>
#include <stdexcept>
class Base {
public:
virtual int type() = 0;
};
class SubClassA : public Base {
public:
virtual int type() override { return 1; }
};
class SubClassB : public Base {
public:
virtual int type() override { return 2; }
};
class BaseConversion {
public:
BaseConversion(Base *ptr) : _ptr(ptr) {}
Base *_ptr;
template<typename T>
operator T() const {
throw std::runtime_error("invalid Base * type()");
}
};
template<>
BaseConversion::operator SubClassA*() const {
if ( _ptr->type() != 1 ) {
throw std::runtime_error("type() not SubClassA");
}
return static_cast<SubClassA*>(_ptr);
}
template<>
BaseConversion::operator SubClassB*() const {
if ( _ptr->type() != 2 ) {
throw std::runtime_error("type() not SubClassB");
}
return static_cast<SubClassB*>(_ptr);
}
int main(int argc, char **argv) {
Base *ptr = new SubClassA();
try {
SubClassA *a = BaseConversion(ptr);
} catch (const std::exception &e) {
std::cout << e.what() << std::endl;
}
try {
SubClassB *b = BaseConversion(ptr);
} catch (const std::exception &e) {
std::cout << e.what() << std::endl;
}
return 0;
}
It does mean you'd need to specialize a template for each subclass of Base. However, this also means you can write a unit test for each which exercises the conversions and helps ensure that you always check for the correct type() id and convert to the correct subclass (by having to only write SubClassA once in the pointer declaration/allocation instead of also in the static_cast).
This won't help you (performance wise) if you do something like this:
switch (ptr->type()) {
case 1:
SubClassA *a = BaseConversion(ptr);
/* do stuff with a */
break;
case 2:
SubClassB *b = BaseConversion(ptr);
/* do stuff with b */
break;
}
...since you'd effectively be checking type() twice. However, as long as type() just returns an integer and doesn't have to do calculations to figure out what type it is, the performance shouldn't be terrible if you do (there are far worse things you could do). Note that, because of static_cast, this does effectively remove any constness of the given pointer! There are probably ways to resolve that but I'll leave that as a further exercise for you since I'm lazy.

Boost::Bind and virtual function overloads: why do they work?

I wrote some code and got scared that it will not work - so I wrote a prototype:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
class base {
private:
boost::function<void (int)> action;
protected:
virtual void onDataBaseReady(int i) { std::cout << i << std::endl; }
public:
void call() {
action(10);
}
base() {
action = boost::bind(&base::onDataBaseReady, this, _1);
}
};
class child : public base {
protected:
virtual void onDataBaseReady(int i) { std::cout << i+10 << std::endl; }
};
int main()
{
static child c;
c.call();
std::cin.get();
return 0;
}
that compiles and works. (outputs 20). But Why? Also I tested under VS2010 and wonder if it would work across platforms (say compiled under GCC)?
Mainly action = boost::bind(&base::onDataBaseReady, this, _1); scares me - we say &base::...
A pointer to a virtual method does a virtual function lookup when called.
#include <iostream>
#include <memory>
struct base {
virtual void foo() { std::cout << "base\n"; }
virtual ~base() {}
};
struct derived:base {
void foo() override final { std::cout << "derived\n"; }
};
int main() {
void (base::*mem_ptr)() = &base::foo;
std::unique_ptr<base> d( new derived() );
base* b = d.get();
(b->*mem_ptr)();
}
so, it "just works". The member function pointer (this->*&base::foo)() is not the same as a fully qualified function call this->base::foo(). The first is a way to store the foo part of calling this->foo(), the second is a way to skip virtual method lookup and directly call base::foo.
Mainly action = boost::bind(&base::onDataBaseReady, this, _1); scares me - we say &base::...
It would actually be much more scary if it performed static dispatch, rather than dynamic dispatch. Consider this simple example:
struct base {
virtual void foo() { /* maintain some invariants */ }
};
struct derived : base {
virtual void foo() { /* maintain different invariants */ }
};
And then consider that you bind the function at the parent and call it on the derived object. The implementor of derived knows what invariants apply to the derived type, which might be the same, a subset or completely different than the invariants in the base type.
void apply(base & b) {
std::bind(&base::foo, &b)();
}
If dispatch was resolved at binding time, and the functor was applied to the derived type (of which you might not know the exact type!) then the invariants of the derived type might be broken. In the context of the apply function it is impossible to know what the object really is, or what the invariants of that type are, so what you probably want to do is let dynamic dispatch do its magic.
[That is from a high level design point of view, without even going into the detail that you cannot use a pointer to member to perform static dispatch...]

How to provide more than one overrides for one virtual function

I have the following classes :
class A {
};
class B : public A {
};
class P {
private:
std::list<A*> l
protected:
virtual void DoIt(A* a) = 0;
public:
void WorkerThread() { for (it=l.begin(); it!=l.end(); it++) DoIt(*it); }
};
class Q : public P
{
protected:
void DoIt(A* a) { print("false"); }
void DoIt(B* b) { print("true"); }
};
Unfortunately, DoIt(B* b) will never get called.
DoIt(A* a) will always be called even if I add B objects to the list.
What can I do to make DoIt(B* b) called ?
Is it possible to achieve this if B does not know Q ?
Is it possible to achieve this if without dynamic cast ?
Thank you
Well, nobody's really directly answered your question (well, heavyd tried) so I will. Some other "answers" here are actually more helpful for fixing your problem though.
The issue is that void DoIt(B*) is NOT an override of the virtual function DoIt(A*). It's an overload. There's a HUGE difference.
When you say that DoIt(B*) is not called when you pass a B* I have to assume that you're holding references or pointers to you Q through a pointer to something higher up the higherarchy. In those cases the static name resolution only finds DoIt(A*) and since B* is-a A* it gets upcasted and that's the version that gets called. Since it is virtual the override in Q is what gets called.
If you had a pointer to Q as a pointer to Q though, and called DoIt with a B* the DoIt(B*) function should get called. At this point, double dispatch is not needed and is not used.
You need double dispatch when you have two abstract types and a function that must behave differently based on the concrete types of both abstractions. This is what you're attempting to do when you call DoIt with B on Q at a higher level than static naming provides. There are too many methods that answer different needs to be able to suggest one solution over another in your case, don't really know what you're trying to solve. In fact, you might not even need it! A better approach for you might be to implement DoIt(B*) as a virtual function in the top of your higherarchy.
I would suggest that you get Andre Alexandrescu's book, Modern C++ Design, and look it over. He explains a pretty darn cool visitor implementation as well as a multiple dispatch mechanism that scales. Don't stop there though, there's other great implementations that can answer the question differently.
Good luck.
You are looking for a double dispatch mechanism that is not built into the language. There are different approaches on how this can be implemented based on the visitor pattern. Google for double-dispatch in C++. Note that this is a patch and not easily extended to big hierarchies:
struct visitor;
struct A {
virtual void accept( visitor& v ) { v(*this); }
};
struct B {
virtual void accept( visitor& v ) { v(*this); }
};
struct visitor {
virtual void operator()( A& ) = 0;
virtual void operator()( B& ) = 0;
};
struct myvisitor : visitor {
void operator( A& ) { std::cout << "A" << std::endl; }
void operator( B& ) { std::cout << "B" << std::endl; }
};
int main() {
std::vector<A*> data = ...
myvisitor v;
for ( std::vector<A*>::iterator it = data.begin(), end = data.end(); it != end; ++it )
{
(*it)->accept( v );
}
}
The usual mechanism will be used and accept will be dispatched to the final overrider of the method, which in turn will call the visitor method. Now, at that point, the static type of the argument to the visitor operator() is in fact the actual type that you want to call the function with.
DoIt(B* b) will never get called because you are never passing in objects of type B*, every time you call DoIt, at least in the given code, you are passing in objects of type A*.
Consider the situation where the override of Doit(A* a) did not exist. Your current code would not compile because it the compiler cannot implicitly cast an object of type A* to B*.
What are you expecting the behaviour to be if someone passes in an A* but the underlying type is really a B?
You might be looking for something like this:
class A
{
public:
virtual ~A() {}
virtual bool isB() const { return false; }
};
class B : public A
{
public:
bool isB() const { return true; }
};
void Q::DoIt( A* a )
{
print( a->isB() ? "true" : "false" );
}
You're looking for multiple dispatch or multimethods. Wikipedia has a nice example for c++; link here.
What you are trying to do is known as multiple dispatch and won't work in C++ because function overloading is static. Take a look at the wikipedia article for some possible work arounds.
For example, if you don't want the logic for the DoIt functionality in the A and B classes themselves as a virtual function then you could use the dynamic_cast method:
class A {
};
class B : public A {
};
class P : protected std::list<A*>
{
protected:
virtual void DoIt(A* a) = 0;
public:
void WorkerThread() { for (it=begin(); it!=end(); it++) DoIt(*it); }
};
class Q : public P
{
protected:
void DoIt(A* a) {
if(B *b = dynamic_cast<B*>(a)) {
// It's a B*, you can "use" b here
print("true");
} else {
// It's an A*
print("false");
}
}
};