Consider the following code:
class A {
public:
virtual ~A() {}
};
class AA : public A {
};
////////////////////////////////////////
class B {
public:
virtual void f(const A &a) {
// code for A
}
};
class BB : public B {
public:
virtual void f(const AA &a) {
// code for AA
}
};
////////////////////////////////////////
int main() {
A *a = new AA;
B *b = new BB;
b->f(*a);
}
Obviously, the vtables are constructed such that when the above is run, // code for A is executed. I am looking for a way to be able to execute instead // code for AA.
The motivation is that this is for a library of code where the end-user will often have to write classes of the form BB, and I would like the process to be as easy as possible (i.e. the user should not have to use RTTI to figure out what derived class of A they are dealing with). Any ideas (and voodoo from any version of the C++ standard) are appreciated.
You can use RTTI and explicitly doing your own dispatching for that.
Co-Variant types only work for return types unfortunately.
Example:
class B {
void f_base(const A &a) {
// code for A
}
public:
virtual void f(const A &a) {
f_base(a); // Moved the base case outside
// to isolate the dispatching mechanism.
}
};
class BB : public B {
public:
virtual void f(const A& a) {
const AA* pAA = dynamic_cast<const AA*>(&a);
if(pAA) {
f(*pAA);
return;
}
f_base(a);
}
void f(const AA &a) {
// code for AA
}
};
More discussion of this type of dispatch as well of nicer packaging with templates is demonstrated here: "type-switch" construct in C++11
You need something that resembles the mechanism that is known as double dispatch, which in C++ can only be implemented indirectly:
class A {
public:
virtual callF(B & b) {
b.f(this);
}
virtual callF(BB & b) {
b.f(this);
}
};
class AA : public A {
public:
virtual callF(B & b) {
b.f(this);
}
virtual callF(BB & b) {
b.f(this);
}
};
This is horrible style but it seems you are under some tight constraints
#include <typeinfo>
// everything else unmodified
class BB : public B {
public:
virtual void f(const A& arg) override {
try { //try to convert to an AA&
const AA& a{dynamic_cast<const AA&>(arg)};
// code for AA
} catch (std::bad_cast) { // if it fails, pass it up to B::f as an A&
this->B::f(arg);
}
}
};
////////////////////////////////////////
int main() {
A *aa = new AA;
A *a = new A;
B *b = new BB;
b->f(*a); // code for A executed
b->f(*aa); // code for AA executed
}
as per Alan Stoke's comment, dynamic casting pointers is much faster when it fails, so you could alternatively use this if you expect failure regularly:
class BB : public B {
public:
virtual void f(const A& arg) override {
const AA* ap = dynamic_cast<const AA*>(&arg);
if (ap == nullptr) {
return this->B::f(arg);
}
const AA& a{*ap}; // get a reference, if you want to
// code for AA
}
};
The concept you are looking for is called double dispatch. Read more about it on http://en.wikipedia.org/wiki/Double_dispatch
It is not built into C++ but there are various ways to emulate it. One of them being the visitor pattern also found in the above link.
However you'll probably find all approaches lacking of elegance because you need to introduce AA to B, BB to A, or use RTTI and casts.
Related
Consider this trivial C++11 inheritance example:
class A
{
public:
virtual void func() = 0;
};
class B : public A
{
public:
void func() { func1(); /* Wish this could be func1() or func2()! */ };
void func1() { /* Does one thing */ };
void func2() { /* Does another thing */ };
};
void doSomeStuff(A &a)
{
a.func();
}
int main()
{
B b;
doSomeStuff(b);
return 0;
}
I'm trying to make it so that I don't have to modify (or duplicate) class A's definition or the function doSomeStuff, but I want the invocation of a.func() to call either func1() or func2() of B. Ideally I'd change the line doSomeStuff(b) to something like doSomeStuff(b.butWithFunc1) but I'd also be OK with some way to modify B's version of func() so that it can make the decision internally to call func1 or func2 based on some parameter.
The same object of type B may have to sometimes call func1 or func2 during an invocation of func, so I can't use a persistent member of class B to decide. Adding a parameter to func() would make this trivial as well, but that's not something I can do either.
I'm kind of wondering if there's some way to add to class B a function that returns a mutated version of class B which calls func2() from func(), or if I can play some tricks with function pointers or something. However, something tells me I'm Doing It Wrong and the obvious solution is staring me in the face.
If it helps for context, class A is similar to a std::lock_guard, and it works fine for things like semaphores and mutexes (for which there is only one definition of lock and unlock), but class B in this example is a R/W lock - so there's a "readLock" and "writeLock", and I'd like to be able to say something like "auto lock this RW lock as a read lock" without having to duplicate/break the auto lock code.
For instance:
{
A_AutoSem(myMutex); // calls lock() on myMutex
//... do some stuff
// end of the block, ~A_AutoSem calls unlock on myMutex
}
{
A_AutoSem(B_RWLock); // how do I say here "call readLock"?
// ... do some stuff
// end of the block ~A_AutoSem should call "readUnlock" on B_RWLock
}
Simply define some additional classes to call func1() and func2(), and then pass those classes to doSomeStuff() instead of passing B directly.
Try something like this:
class A
{
public:
virtual void func() = 0;
};
class B
{
public:
void func1() { /* Does one thing */ };
void func2() { /* Does another thing */ };
};
class C1 : public A
{
private:
B &m_b;
public:
C1(B &b) : m_b(b) {}
void func() override { m_b.func1(); }
};
class C2 : public A
{
private:
B &m_b;
public:
C2(B &b) : m_b(b) {}
void func() override { m_b.func2(); }
};
void doSomeStuff(A &a)
{
a.func();
}
int main()
{
B b;
{
C1 c(b);
doSomeStuff(c);
}
{
C2 c(b);
doSomeStuff(c);
}
return 0;
}
Live Demo
Alternatively:
class A
{
public:
virtual void func() = 0;
};
class B
{
private:
void func1() { /* Does one thing */ };
void func2() { /* Does another thing */ };
public:
class C1 : public A
{
private:
B &m_b;
public:
C1(B &b) : m_b(b) {}
void func() override { m_b.func1(); }
};
class C2 : public A
{
private:
B &m_b;
public:
C2(B &b) : m_b(b) {}
void func() override { m_b.func2(); }
};
};
void doSomeStuff(A &a)
{
a.func();
}
int main()
{
B b;
{
B::C1 c(b);
doSomeStuff(c);
}
{
B::C2 c(b);
doSomeStuff(c);
}
return 0;
}
Live Demo
I understand how C++ solves the diamond problem in multiple inheritance by using virtual inheritance. Suppose the following situation:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C : public A {
void fooc() { int x = get_num(); }
};
class D : public B, public C {
void food() { int x = get_num(); }
};
The get_num() call is ambiguous inside food(). I know I can fix it either by calling A::get_num() or by virtual inheritance using virtual public A. But I can see a third approach:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C { // won't inherit from A anymore
const A& base; // instead keeps a reference to A
void fooc() { int x = base.get_num(); }
public:
explicit C(const A* b) : base(*b) { } // receive reference to A
};
class D : public B, public C {
void food() { int x = get_num(); }
public:
D() : C(this) { } // pass "this" pointer
};
The external code doesn't need to consider C as an A.
Considering it has no impacts on my particular class hierarchy design, are there any advantages of the third approach over the virtual inheritance way? Or, in terms of cost, it ends up being the same thing?
Congratulations ! You've just re-invented the principle of composition over inheritance !
If this works with your design, it means that C was in fact not a kind of A, and there was no real justification to use inheritance in first place.
But don't forget the rule of 5 ! While your approach should work in principle, you have a nasty bug here : with your current code, if you copy a D object, its clone uses the wrong reference to the base (it doesn't refer to it's own base, which can lead to very nasty bugs...
Demo of the hidden problem
Let's make A::get_num() a little bit more wordy, so that it tells us about the address of the object that invokes it:
int get_num() const {
cout << "get_num for " << (void*)this <<endl;
return num;
}
Let's add a member function to C, for the purpose of the demo:
void show_oops() { fooc(); }
And same for D:
void show() { food(); }
Now we can experiment the problem by running this small snippet:
int main() {
D d;
cout<<"d is "<<(void*)&d<<endl;
d.show();
d.show_oops();
D d2=d;
cout<<"d2 is "<<(void*)&d2<<endl;
d2.show();
d2.show_oops();
}
Here an online demo. You will notice that d2 does produce inconsistent results, like here:
d is 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
d2 is 0x7fffe0fd11b0
get_num for 0x7fffe0fd11b0
get_num for 0x7fffe0fd11a0 <<< OUCH !! refers to the A element in d !!
Not only do you refer to the wrong object, but if the d object would decease, you would have a dangling reference, so UB.
Let's say I have the following code:
struct Z;
struct A
{
virtual void Do (Z & z) const;
};
struct B : public A {};
struct Z
{
void use (A const & a) {}
void use (B const & b) {}
};
void A::Do(Z& z) const{
z.use(*this);
}
Right now, when I call B.do, the type of this is A, which make sense, because the implementation of do is defined in A.
Is there any way to have calls to B.do use use (B const &) without having to copy-paste the same code for do from A into B? In my actual code I have about 15 (and growing) classes derived from some base class and it seems a waste having to copy-paste the identical code for do everytime.
[Edit] Clarification: all Do does is call use, nothing else. Do and use are the accept & visit functions from the Visitor pattern.
Since you now clarified that what you want is the visitor pattern, well, sorry, but that's just how it is. This answer shows how the visitor pattern with double dispatch works.
I thought of a nice way using CRTP, but this may or may not work for you, depending on the circumstances.
(Note: I used the code from the linked answer, so the names don't match, but I hope you get the idea.)
// your Z
class Visitor;
// superclass needed for generic handling
struct Superbase{
virtual void Accept(Visitor& v) = 0;
};
// your A
template<class Der>
class Base : public Superbase{
public:
void Accept(Visitor& v){
v.Visit(static_cast<Der&>(*this));
}
};
// your B
class Derived1 : public Base<Derived1> {
};
// new C
class Derived2 : public Base<Derived1> {
};
class Visitor {
public:
virtual void Visit(Superbase& sup){
// generic handling of any Superbase-derived type
}
virtual void Visit(Derived1& d1){
// handle Derived1
}
virtual void Visit(Derived2& d2){
// handle Derived1
}
};
int main(){
Visitor v;
Derived1 d1;
d1.Accept(v);
}
The only problem: Now you're missing the chance to have a generic handle to any type of A, since functions can't be both virtual and templates. :|
Scrape that, found a solution using a Superbase base class. :) This even allows you to have a container of Superbases and take full advantage of polymorphism. :)
I think this code does what you want:
#include <iostream>
struct A;
struct B;
struct Z
{
void use (A const & a);
void use (B const & b);
};
template<typename DERIVED>
struct XX
{
void Do(Z& z){
Do(z,THIS());
}
private:
const DERIVED& THIS() const { return static_cast<const DERIVED&>(*this); }
void Do(Z& z, const DERIVED& t){
z.use(t);
}
};
struct A : public XX<A> {};
struct B : public XX<B> {};
void Z::use (A const & a) { std::cout << "use for A" << std::endl; }
void Z::use (B const & b) { std::cout << "use for B" << std::endl; }
int main(){
A a;
B b;
Z z;
a.Do(z);
b.Do(z);
return 0;
}
The only 'maintenance' or 'boiler-plate' part of the code is to derive from the template class templated on your own type.
You need to dispatch the call of use based on the type pointed to by this so you need to add another virtual function to A and B that simply invokes the correct use. I assume that do does other things than call use of course otherwise you would indeed have to re-implement do in each subclass. It would look like this
struct A
{
virtual void Do (Z & z) const
{
// do stuff
use(z);
// do more stuff
}
virtual void use(Z & z) const
{
z.use(*this);
}
};
struct B : public A
{
virtual void use(Z & z) const
{
z.use(*this);
}
};
struct Z
{
void use (A const & a) {}
void use (B const & b) {}
};
I think I have to disappoint you and say no. This is the trade off you have to make, in order for you to break out the interface from your classes into the visitor. The visitor must know which one is reporting to it, as long as you don't override the virtual Do() in the base class, the visitor will treat you as A.
Please someone prove me wrong! (I'd also see this solved to remove redundancy)
#include<iostream>
using namespace std;
class Abs
{
public:
virtual void hi()=0;
};
class B:public Abs
{
public:
void hi() {cout<<"B Hi"<<endl;}
void bye() {cout<<"B Bye"<<endl;}
};
class C:public Abs
{
public:
void hi() {cout<<"C Hi"<<endl;}
void sayonara() {cout<<"C Sayonara"<<endl;}
};
int main()
{
Abs *bb=new B;
bb->bye();
Abs *cc=new C;
cc->sayonara();
}//main
The compiler says
test2.cpp: In function ‘int main()’:
test2.cpp:26: error: ‘class Abs’ has no member named ‘bye’
test2.cpp:28: error: ‘class Abs’ has no member named ‘sayonara’
Because of this problem, I'll have to add functions to the Abs class each time I create a new derived class which inherits from it (Upcasting is compulsory for me to do. The program I'm planning requires it to be so). I don't want to touch the base class once it's created.
Doesn't this problem violate the principle that once you make a base class, you won't have to modify it ever. Any way to resolve this problem?
p.s: I've seen the factory design pattern and the prototype design patterns, but both of them can't seem to be able to solve it.
This is defeating the purpose of inheritance and abstract interfaces. bye and sayonara both do the same thing (saying goodbye), only in different languages. This means you should have an abstract say_goodbye method that gets overridden for subclasses. I suppose this is a simplified example, so maybe you could describe your actual scenario so we can provide more specific help.
Edit If you want to create a copy of the derived class through an abstract interface, check out this question. If you want to explicitly access the different attributes of your subclasses, you should be asking your self if subclassing es even appropriate here, since your classes don't seem to have much in common.
Well, i'm not sure to understand exactly what you want (and why you want it that way) but:
int main()
{
Abs *bb=new B;
static_cast<B*>(bb)->bye();
Abs *cc=new C;
static_cast<C*>(cc)->sayonara();
}//main
Will work.
You just have to be sure that bb is really a B* before you static_cast.
You may also use dynamic_cast which will return a null pointer if bb is not of the correct type.
int main()
{
B *bb = new B;
bb->bye();
C *cc=new C;
cc->sayonara();
}//main
This way modifications in the base class are no longer needed :)
Dynamic casting is a sensible option. If you're religious about dynamic casts, you can use the visitor design pattern:
struct Abs;
struct B;
struct C;
struct Visitor
{
virtual ~Visitor() {}
// Provide sensible default actions
virtual void visit(Abs&) const { throw "not implemented"; }
virtual void visit(B& b) const { visit(static_cast<Abs&>(b)); }
virtual void visit(C& c) const { visit(static_cast<Abs&>(c)); }
};
struct Abs
{
virtual ~Abs() {}
virtual void hi() = 0;
virtual void accept(Visitor const& v) { v.visit(*this); }
};
struct B : Abs
{
void hi() { ... }
void accept(Visitor const& v) { v.visit(*this); }
void bye() { ... }
};
struct C : Abs
{
void hi() { ... }
void accept(Visitor const& v) { v.visit(*this); }
void sayonara() { ... }
};
struct DoSayonara : Visitor
{
void visit(C& c) const { c.sayonara(); }
};
struct DoBye : Visitor
{
void visit(B& b) const { b.bye(); }
};
struct ByeOrSayonara : Visitor
{
void visit(B& b) const { b.bye(); }
void visit(C& c) const { c.sayonara(); }
};
and then you use
Abs* b = new B(); Abs* c = new C();
b->accept(DoSayonara()); // Throw an exception
c->accept(DoSayonara()); // Do what is expected
Do this only when you really need it.
If upcasting is compulsory and you need to call methods defined in the subclasses then You're Doing It Wrong.
However, at a given point in time, you either know that an object is a specific subclass, in which case you can dynamically cast to that type, or you don't and can't be sure you can call the function.
Assuming this is related to your other question, I've tried to explain a way to implement that particular problem in a different manner there.
Scenario: I have the following defined classes.
class Baseclass { };
class DerivedTypeA : public Baseclass { };
class DerivedTypeB : public Baseclass { };
// ... and so on ...
class Container
{
list<Baseclass*> stuff;
list<DerivedTypeA*> specific_stuff;
// ... initializing constructors and so on ...
public:
void add(Baseclass * b)
{
stuff.add(b);
}
void add(DerivedTypeA * a)
{
stuff.add(a);
specific_stuff.add(a);
}
};
class ContainerOperator
{
Container c;
// ... initializing constructors and so on ...
public:
void operateOnStuff(Baseclass * b)
{
// This will always use "void add(Baseclass * b)" no matter what object b really is.
c.add(b);
}
};
// ...
containerOperator.operateOnStuff(new DerivedTypeA());
So, what I want to do is to handle a certain derived class in some special way in Container.
Problem: void add(DerivedTypeA * a) is never called. I'm obviously doing something wrong. What is the correct way of doing what I am trying to achieve here?
Overload resolution in C++ happens at compile-time, not run-time. The "usual" way to solve problems like this is to use Visitor pattern.
You can reduce the amount of boilerplate copy-paste by implementing Visitor with CRTP.
If you use CRTP for Base::accept, you don't need to define it any more in derived classes.
Here is a similar program to yours, but a little simpler:
#include <iostream>
class Base; class Derived;
struct Operation {
void add(Base *b) {
std::cout << "Base\n";
}
void add(Derived *b) {
std::cout << "Derived\n";
}
void visit(Base *b); // need to define this after Base class
};
struct Base {
virtual ~Base() {}
virtual void accept(Operation &o)
{
o.add(this);
}
};
void Operation::visit(Base *b) {
b->accept(*this);
}
struct Derived : public Base {
void accept(Operation &o)
{
o.add(this);
}
};
int main() {
Operation o;
Base b;
Derived d;
Base *ptrb = &b;
Base *ptrd = &d;
o.add(ptrb); // These two print "Base"
o.add(ptrd);
o.visit(ptrb); // "Base"
o.visit(ptrd); // "Derived"
}
You can use RTTI to determine whether the provided object is of the derived type, and if so, call the second add() function.
void add(Baseclass * b)
{
stuff.add(b);
DerivedTypeA * a = dynamic_cast<DerivedTypeA *>(b);
if ( a != 0 )
specific_stuff.add(a);
}
Unlike the visitor pattern this solution violates the Open-Closed Principle, but it's a lot simpler and easier to understand when the number of derived classes do not change or change slowly over time.