Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I implement different implementation to same function from different base classes?

Assume the following:

class A{ virtual void f() = 0; };
class B{ virtual void f() = 0; };

Can I do the following somehow?

class C : public A, public B
{
  virtual void A::f(){ printf("f() from A"); }
  virtual void B::f(){ printf("f() from B"); }
};

So now I can do???

A* pa = new C();
pa->f(); // prints f() from A;
B* pb = (B*)pa;
pb->f(); // prints f() from B;

Thanks!!!

like image 805
TCS Avatar asked Dec 22 '13 14:12

TCS


People also ask

Can you inherit from multiple base classes in c#?

But C# does not support multiple class inheritance. To overcome this problem we use interfaces to achieve multiple class inheritance. With the help of the interface, class C( as shown in the above diagram) can get the features of class A and B.

Can a derived class have two base classes?

You can derive a class from any number of base classes. Deriving a class from more than one direct base class is called multiple inheritance. The order of derivation is relevant only to determine the order of default initialization by constructors and cleanup by destructors.

What is multiple base class?

A class can be derived from more than one base class. In a multiple-inheritance model (where classes are derived from more than one base class), the base classes are specified using the base-list grammar element.


1 Answers

First solution

This question remind the 'facade' design pattern. This should be re-write as this :

class AC : public A
{ public: virtual void f(){ cout << "f() from A" << endl;}; };

class BC : public B ...

class C : public AC, public BC {};

where C is the 'facade'.

So in the correct calling syntax should be something like that :

C* c = new C();
c->AC::f();
c->BC::f();

If you don't have any share constraint between AC & BC this should do the job as it is'nt offuscated.

Second solution

Another solution, thank to Casey (see first comment), is to use a forward declaration of the class C in a template to allow calls to methods define latter.

template <typename C>
class AC : public A {
public:
    void f() { static_cast<C&>(*this).f_from_A(); }
};

template <typename C>
class BC : public B { ... };

so the implementation part can be done in the same class.

class C : public AC<C>, public BC<C> {
public:
    void f_from_A() { cout << "f_from_A" << endl; };
    void f_from_B() ...
};

The calling part is cleaner because it doesn't show any implementation details and it is closest to the question :

C* c = new C();
((A*) c) -> f();
((B*) c) -> f();

There is no more 'default' f() on C and it is possible to break the expected behavior of inheritance, and it is harder to read.

like image 140
Galigator Avatar answered Sep 30 '22 02:09

Galigator