avoid specifying functions to call in diamond design - c++

I have a diamond design currently, and I saw a related question here
In that question, let me assume that class B and class C are virtual inherited from Class A, so in Class D, when we need to call virtual functions, we need to specify which one needed to call.
D::foo()
{
B::foo(); //specify foo() in B
}
For my diamond design, I have a lot of virtual functions to rewrite, in order to let these functions called by correct B or C father class functions.
It is not good, a lot of repeated work need to be done, when I have child class, do you have some better solutions, so that I can call foo() of B in class D but no rewrite for the example above.

Since C++11, you can do an aliasing:
class A
{
public:
virtual void foo() { cout << "A" << endl; }
}
class B : public virtual A
{
public:
void foo() { cout << "B" << endl; }
}
class C : public virtual A
{
public:
void foo() { cout << "C" << endl; }
}
class D : public B, C
{
using B::foo;
}
This way, doin:
D obj;
obj.foo();
Will output B;

I think template classes might do the trick here.
http://www.cplusplus.com/doc/tutorial/templates/

Related

Can I do/mimic things likes this (partial override) in C++?

I have two classes A and B, both defining method m(). Although the signatures of these methods are the same, they are two totally different methods with different meanings. In class C, I want to update both m(). Instead of writing a new m() in class C that fuses the two m() from A and B, I want to override them separately. See the following code:
class A { public: virtual void m() {cout << "MA" << endl;}};
class B { public: virtual void m() {cout << "MB" << endl;}};
class C : public A, public B {
public: virtual void m() update A {cout << "MA2" << endl;}};
public: virtual void m() update B {cout << "MB2" << endl;}};
}
void func(A* a) { a->m(); }
int main() {
C* c = new C();
c->B::m(); //print "MB2"
func(c); //print "MA2"
return 0;
}
I know that the update syntax is not supported in C++, but is there any workaround to simulate this in C++?
A nasty part of multiple inheritance is that indeed there is only one m in C that overrides both. You need a middle-man class to disambiguate the call in case of 2 or more classes that define m. Fortunately, you can use a template in order to automate the process:
template<class C>
class MiddleMan : public C {
void m() override final { m_impl(this); }
protected:
virtual void m_impl(MiddleMan*) = 0;
};
Now you just use this template and override the new functions it adds:
class C : public MiddleMan<A>, public MiddleMan<B> {
private:
void m_impl (MiddleMan<A>*) override {cout << "MA2" << endl;}
void m_impl (MiddleMan<B>*) override {cout << "MA2" << endl;}
};
The implementation of m in each middle man class will call the new virtual functions that are overloaded. You then define these overloads. I used MiddleMan* as the extra parameter which facilitates overloading, but any type which is cheap to pass by value and depends on the template parameter will do for disambiguation.
You just cannot do that, for the same reason in C you can't have two functions with the same name: the compiler would not know which one to call!
To get the same effect that you want, I'd change your code to look as follows:
class A { public: virtual void ma() {cout << "MA" << endl;}};
class B { public: virtual void mb() {cout << "MB" << endl;}};
class C : public A, public B {
public: virtual void ma() override {cout << "MA2" << endl;} // these are *extra*: };
public: virtual void mb() override {cout << "MB2" << endl;} // these are *extra*: };
}
void func(A* a) { a->ma(); } // the problem here with a->m() would be
// that the compiler would not know which m() function to call --
// you basically want two pointers *crammed* somehow in the same vfptr entry,
// and the compiler to *automagically* know which one to call,
// depending on... unspecified conditions!
int main() {
C* c = new C();
c->B::m(); //this will never print "MB2" in your code;
//it will always print "MB", no matter what you do!
c->mb(); //print "MB2"
func(c); //print "MA2"
return 0;
}
I know, this may not be the answer you're looking for, but then you have to describe your problem better. In my opinion, this is a valid solution to your problem, as it's currently described.

how to combine two classes that share the same base class in C++?

I give the following example to illustrate my question:
class Base
{
public:
virtual void do()=0;
}
class A: public Base
{
public:
void do();
};
class B: public Base
{
public:
void do();
}
class AB: public Base
{
public:
void do()
{
a_.do();
// if not succeed
{
b_.do();
}
}
private:
A a_;
B b_;
}
From the above codes, we can see that class A, B and AB come from the same Base class. class AB, however, needs to invoke both class A and class B. Here is my question: what's the potential problem with the class AB? Are there other alternatives?
One alternative might be:
class Base
{
public:
virtual void do()=0;
}
class A: public Base
{
public:
void do();
};
class B: public Base
{
public:
void do();
}
class AB: public A
{
public:
void do()
{
A::do();
// if not succeed
{
b_.do();
}
}
private:
B b_;
}
I have no idea what you really want to achieve. But if all of your classes should only have one copy of instance data from Base, you need a virtual Base class.
The problem from your first example with AB is, that you have three! times data of class Base. One from inherit Base, one as part of Member B which itself derives from Base and the same from Member A. Is that what you intend?
I give you the following snipped to see how you can work with exact ONE copy of Base in all of your class instances. Maybe that is what you want to get?
I add some data to Base to see how construction works while using virtual base classes. It is important that the base class constructor will not be called from the constructors of directly inherited classes! You need to call the constructor directly from the outermost constructor as shown in class AB constructor!
As a remark: Virtual Base classes should be used only if nothing else fits the design. Often the need of such a solutions shows a design problem. But as always in programming: If this fits exactly your needs, it is technically absolutely ok to do it.
class Base
{
private:
std::string text;
public:
Base( const std::string& str ): text(str) {}
virtual void Do() { std::cout << text << std::endl; }
};
class A: virtual public Base
{
public:
A():Base("Default from A") {}
void FuncA() { std::cout << "FuncA" << std::endl; }
void Do() { std::cout << "Via A" << std::endl; Base::Do();}
};
class B: virtual public Base
{
public:
B(): Base ("Default from B") {}
void FuncB() { std::cout << "FuncB" << std::endl; }
};
class AB: public A,B
{
public:
//Important to know that init of Base MUST be done from here and not from A nor B !!
AB( const std::string &s): Base(s) {}
void Do() { std::cout << "Via AB" << std::endl; Base::Do(); A::Do(); B::Do();}
};
int main()
{
A a;
a.Do();
std::cout << "####" << std::endl;
B b;
b.Do();
std::cout << "####" << std::endl;
AB ab("Hallo");
ab.Do();
std::cout << "####" << std::endl;
}
what's the potential problem with the class AB?
I don't know of any well known problem that would necessarily arise from your design. You should ask yourself "Why would there be a problem?".
Are there other alternatives?
There are many alternatives. For example, neither A nor B contain any state, so you could just as well stop using classes in favor of free functions and replace dynamic binding with a function pointer.
To be able to compare different alternatives, you should first decide what problem you are trying to solve.
You should inherit from A and B and not from Base, because A and B already do so.

Accessing child class from parent class

First of all I'm sorry if this is asked already but I couldn't find answer.
So, can I have class A and it inherits class B, can I access class A function from class B?
This is just example.
class A : public B
{
void aFoo() { cout << "A" << endl; }
};
class B
{
void bFoo() { aFoo(); }
};
So, is this possible in any way and if it is how it can be done?
You could use a virtual function in B and reimplement it in A, however you still have to create the object as A, for example:
class A : public B {
void aFoo() { cout << "A" << endl; }
};
class B {
void bFoo() { aFoo(); }
virtual void aFoo() { cout << "B" << endl; } //or
virtual void aFoo() = 0; // turning B into an abstract class.
};
.......
B* ab = new A;
Yes (with templates)... You can use the Parent class as a template class which receieves the the Type of its child, so it can cast itself to that type... e.g.:
template <typename T>
class A
{
public:
A() = default;
void afoo()
{
reinterpret_cast<T*>(this)->bfoo();
}
};
class B : public A<B>
{
public:
B() = default;
void bfoo()
{
std::cout << "In B::bfoo()";
};
};
int main()
{
B b;
b.afoo();
}
This way you can avoid virtual inheritance.
No. Derived classes can access base class members and methods if declared public/protected. It does not work the other way round.
So, is this possible in any way and if it is how it can be done?
No. You can't. Note that inheritance doesn't work in reverse. The base class and its objects don’t know anything about any classes derived from the base class.
If your question is about whether it is possible syntactically, then as others have answered - No you can't because that's not how it works.
However, if you are looking for a design pattern to solve an issue in which this is something you would like to have, then I think what you are looking for is a Bridge Pattern where the parent class calls a virtual function which is implemented differently in each different child class (exactly what OneofOne answered).
More about the Bridge Pattern: http://sourcemaking.com/design_patterns/bridge/cpp/1

Strange behavior with virtual functions

With the following code, I would expect output to be B.f B.f DD.f, but instead the output I get is B.f B.f B.f. How is that possible, when DD derives from D which has f as virtual.
class B
{
public:
void f() { cout << "B.f "; }
};
class D : public B
{
public:
virtual void f() { cout << "D.f "; }
};
class DD : public D{
public:
virtual void f() { cout << "DD.f "; }
};
B * b = new B();
B * d = new D();
B * dd = new DD();
b->f();
d->f();
dd->f();
Functions become virtual from the level they were declared virtual up. You first declare f virtual in D, which means the dynamic dispatch will only happen from D upwards. B doesn't, nor should it know about the deriving classes.
Think about how the compiler sees it:
You have a pointer to B - B has the following definition:
class B
{
public:
void f() { cout << "B.f "; }
};
Since f is not virtual, I'll just go ahead and resolve the call statically - i.e. B::f().
For dynamic dispatch to work from a pointer to B, you need to make f() virtual in B:
class B
{
public:
virtual void f() { cout << "B.f "; }
};
You need to set B::f() to virtual, without set B::f() to virtual, it won't appear in B virtual table(vtbl), thus B::f() is called instead of dispatch the call to derived class.
class B
{
public:
virtual void f() { cout << "B.f "; }
};
As soon as you declare f() virtual in B,this starts to maintain a virtual table that holds the function pointers of all the other functions of same name of derived classes. This is a lookup table that is used to resolve function calls in a dynamic/late binding manner.
When you use a reference or a pointer to call a method, the compiler searches in the type of the pointer or reference at the declaration of the method (here it searches in B the declaration of some method with signature f()). When it finds one :
if it is NOT marked as virtual, then it solves it as a call to the method defined for this class - this is a static binding.
if it is marked as virtual, then the method called will be the appropriate one of the object referenced or pointed by - this is a dynamic binding.
The next test would have been :
DD * dd = new DD();
D * d = dd;
B * b = d;
b->f();
d->f();
dd->f();
One single object new DD() that is used/viewed differently... Each type can be thought as a kind of view you have on an object. If you see it as a B then f() does something but always the same thing, but if you see it as D or DD, f() does something different...
If you meet someone in the street, the standard way for him to salute you is to say hello, but for the same person, when he meets a friend of him he can either say hi! or Yo! :
class Person {
public:
void salute() { cout << "Hello" << endl; }
};
class Friend : public Person {
public:
virtual void salute() { cout << "Hi!" << endl; }
};
class RoomMate : public Friend {
public:
virtual void salute() { cout << "Yo!" << endl; }
};
void asACustomer(Person &p) {
p.salute(); // static binding, we need the standard politeness
}
void asAFriend(Friend &f) {
p.salute(); // dynamic binding, we want an appropriate message...
}
RoomMate joe;
asCustomer(joe);
asFriend(joe);
With static binding you know at compile time which method is called; with dynamic binding you cannot, you only know that an appropriate one will be. This is a key point in sub-typing polymorphism.
In general, be careful when mixing static and dynamic binding for a method.

Inheritance from two abstract classes

I have a problem that I have not yet tested/compiled and wondering if it is possible and if it is bad design?
My Problem:
I want to have an abstract base class A and a abstract derived class B.
I realize if this is possible I will have a number of pure virtual member functions in each class and also I will not be able to initialize these objects, but that is a given for abstract classes.
In my design I will have another derived class C which I would then initialize - class C would be derived from class B.
I would have something that looked like this
class C
^
|
abstract class B
^
|
abstract base class A
My Question:
Is this possible first of all? I would suspect so, but not declaring the pure virtual functions in A in class B may be troublesome?
e.x.
class A {
public:
virtual void test()=0;
};
class B: public A {
public:
virtual void test()=0;
virtual void anotherTest()=0;
};
Is the above okay?
Is this bad c++ design? In future I will have derived classes from A so it would be nice to have this design.
Nothing wrong with it, and it will certainly work. Example follows
stefanos-imac:dftb borini$ more test.cpp
#include <iostream>
class A {
public:
A(void) { std::cout << "A" << std::endl; }
virtual void method1() = 0;
};
class B : public A {
public:
B(void) : A() { std::cout << "B" << std::endl; }
virtual void method2() = 0;
};
class C : public B {
public:
C(void) : B() { std::cout << "C" << std::endl; }
virtual void method1() { std::cout << "method1" << std::endl; }
virtual void method2() {std::cout << "method2" << std::endl; }
};
int main() {
C c;
c.method1();
c.method2();
}
stefanos-imac:dftb borini$ ./a.out
A
B
C
method1
method2
Thank you for reminding me that I can still type basic C++.