I have the following code.
#include <iostream>
class Base1
{
public:
void print(){std::cout<<"Printing Base1\n";}
};
class Derived1: public Base1
{
public:
void print_1(){std::cout<<"Printing Derived1 \n";}
};
class Base2
{
public:
void myFunction1( Base1& b1)
{
myFunction2(b1);
}
virtual void myFunction2( Base1& b1)
{
b1.print();
}
};
class Derived2: public Base2
{
public:
void myFunction2( Derived1& d1)
{
d1.print_1();
}
};
int main()
{
Base1 b1;
Derived1 d1;
Base2 b2;
Derived2 d2;
b2.myFunction1(b1);
d2.myFunction1(d1);
return 0;
}
It results in the following output:
Printing Base1
Printing Base1
I thought of getting the following output
Printing Base1
Printing Derived1
One of the ways to get the desired output is to do the following.
class Derived2: public Base2
{
public:
void myFunction2( Base1& b1)
{
Derived1* d1 = static_cast<Derived1*> (&b1);
d1.print_1();
}
};
I would like to allow Derived2 to only deal with Derived1 and not with Base1. Otherwise, Some user may call Derived2::myFunction2 with Base1 object which can crash the program in such cases.
Is there a good solution?
myFunction2() in Derived2 does not override myFunction2() in Base2.
A virtual function gets overridden only if its signature matches, exactly. The function in this derived class takes a different parameter than the one in the base class. Hence, it does not override.
You have to make it override, as your first step.
class Derived2: public Base2
{
public:
void myFunction2( Base1& d1) override;
};
Now it's overridden. If you explicitly specified the override qualifier, as I did here, your compiler would've yelled at you already.
Now, your goal is to have whatever myFunction2 does, only have it take in effect for Derived1 class, and for all other Base1 classes, use what the superclass does.
Ok. This will require a little bit more work, and it will be slightly difficult to follow along. What needs to happen is another virtual inheritance, in Base1 this time:
class Derived2: public Base2
{
public:
void myFunction2( Base1& d1) override
{
d1.print_from_Derived2( *this );
}
};
Now, you need to define Base1::printDerived2(), which will invoke print(), which is what should happen in this case, according to your question:
class Base1
{
public:
virtual void print_from_Derived2( Derived2 &)
{
print();
}
};
And now, override it in Derived1 in order to put the last piece of the puzzle together:
class Derived1 : public Base1
{
public:
void print_from_Derived2( Derived2 &) override
{
// Do whatever print() from Derived2 needs to do, for
// this object, which is Derived1.
}
};
And here, you will do whatever needs to be done for Derived2 to print only Derived1. It's a bit of a circuitous route, but you finally reached the place where both actors are Derived1 and Derived2, without breaking any rules, and without any ugly casts.
You will need to do a bunch of forward declarations here, in order to stitch together all of these moving pieces. My examples are just brief simplifications, and they obviously have mutual references to each one, and will have to be broken apart into separate declarations and definitions, with appropriate forward declarations.
Related
I've never used multiple inheritance in C++ before, but i got curious since i've seen an implementation of a braided bst, by means of a multiple inheritance of a base class List and a base class BinarySearch tree in a book.
Now i was trying to make up some stupid example in order to understand how it works.
So i came up with this:
class Base1 {
public:
virtual void method();
};
class Base2 {
public:
virtual void method();
};
class Derivate : public Base1, Base2 {
};
In the main i've done something like this:
Derivate d;
d.method();
The code doesn't compile, there's other code which implements both methods, but i don't post all the code because i think i make my point anyway.
To me it sounds fair that it doesn't compile because probably it isn't known which method specifically the derivate class should refer to, however it could happen that two base classes i want to extend actually shares a method name (think to both list and bst you can have a method both a method "insert" and "delete") so in general how for this "critical cases" the multiple inheritance works? in case like the one i presented is there a way to solve in a elegant way the problem?
You can write:
class Derivate : public Base1, Base2 {
public:
using Base1::method;
};
In case of cases like this, you got to mention the class of the method that you want to call.
.
.
Found a very detailed answer to the question here
I think it may be an example to show the magic power of the virtual method in cpp.In the main you can use a pointer to have some interesting output.
#include <iostream>
using namespace std;
class Base1 {
public:
virtual void method(){
cout<<"Base1 method"<<endl;
};
};
class Base2 {
public:
virtual void method(){
cout<<"Base2 method"<<endl;
};
};
class Derivate : public Base1, Base2 {
public:
void method(){
cout<<"Derivate method"<<endl;
}
};
int main() {
Derivate d;
Base2 bs2;
Base1 bs1;
Base1* ptr=&bs1;
ptr->method();
ptr=&d;
ptr->method();
}
In this way ,you can have
Base1 method
Derivate method
as an output.
And if you don't rewrite the method in class Derivate ,just like:
class Derivate : public Base1, Base2 {
public:
void method(){
//cout<<"Derivate method"<<endl;
}
};
in the main, if you use Base1* ptr=&d,ptr->method()you will call the method in Base1;else if you use Base2* pt=&d,pt->method()you will call the method in Base2.
Moreover,you can also rewrite the method maybe like:
class Derivate : public Base1, Base2 {
public:
virtual void method(){
Base1::method();
Base2::method();
}
};
I have a basic base class and a couple of sub-classes which inherit from it.
Class Base{
public:
Base(){};
virtual ~Base();
virtual void foomethod()=0; //Marked as pure virtual
};
Class A : public Base{
A(){}; //Ctor
~A(){}; //Dtor
void foomethod(){ /* DO SOMETHING */ }
}
Class B : public Base{
B(){}; //Ctor
~B(){}; //Dtor
void foomethod(){ /* DO SOMETHING */ }
}
Use of the above is throwing an error in the following usage:
Base a = A();
Base b = B();
The compiler is complaining about the function foomethod() being pure virtual.
However, when the following is used, there is no problem.
A a = A();
B b = B();
I would have thought that the first instance should be accepted due to C++'s principles of polymorphism. I want to enforce a specific method implementation of the method in sub-classes. If it is marked as virtual only, there is not guarantee that it will be explicitly overrided.
There are several issues with your code, I'll try to get most of them:
You can't have a pure function without marking it as virtual
You can't create objects of an abstract Base class (there's no code for the methods)
When you write
Base b = A();
you're creating two objects and then assigning the A object to the Base b object. This cannot happen since Base is abstract but in cases where this can happen you could experience the slicing problem.
You marked the destructor as virtual in the derived classes but not in the Base (and no definition either), always mark it as virtual when using virtual polymorphism otherwise derived destructors will not be called
This is a more correct way of doing it:
#include <iostream>
using namespace std;
class Base{
public:
Base(){};
virtual ~Base() {};
virtual void foomethod()=0; //Marked as pure virtual
};
class A : public Base{
public:
A(){}; //Ctor
virtual ~A(){}; //Dtor
void foomethod(){ cout << "Hello from A"; }
};
class B : public Base{
public:
B(){}; //Ctor
virtual ~B(){}; //Dtor
void foomethod(){ /* DO SOMETHING */ }
};
int main() {
// Base obj; // Can't do that
Base *obj = new A();
obj->foomethod(); // A's one
delete obj;
return 0;
}
http://ideone.com/gvcL9S
Oh and there were some syntax errors here and there.. and a visibility problem if you intend to use those functions from the outside.. but I believe the excerpt was just a pseudocode one.
Here are my classes:
class Base1
{
public:
Base1();
~Base1();
virtual void main_func()=0;
}
class D1 : public Base1
{
public:
D1();
~D1();
virtual void main_func(do_d1_main(););
}
class D2 : public Base1
{
public:
D2();
~D2();
virtual void main_func(){do_d2_main();};
}
class Base2
{
public:
Base2();
~Base2();
int m_needed_by_b1;
}
class D12B2: public Base2, public D1, public D2
{
public:
D12B2();
~D12B2();
}
Here's the problem:
Both do_main_func1() and do_main_func2() need access to member m_needed_by_b1 in Base2. How?
Could I define the virtual function main_func for each within class D12B2? That would give them access to all of D12B2, including Base2. How would I specify each separately?
I thought about adding a (protected) member in Base1, that is a pointer to a Base2 object. That would have to be set by D12B2. It seems like there might be a more elegant way to do this.
TIA
ken
It seems like there might be a more elegant way to do this.
More than likely, there is - don't use multiple inheritance.
However, if you are going to insist on using multiple inheritance, there are some things you must note: D1 and D2 should be inherited virtually in D12B2 to avoid the diamond problem. Assuming do_d1_main and do_d2_main actually means main_func, then you can implement a D12B2::main_func that will be able to access m_needed_by_b1.
But back to the original note:
It sounds like Base1 and Base2 should not exist, and D1 and D2 should be pure abstract classes. Which would leave you with
class D1
{
public:
virtual void d1_func() = 0;
};
class D2
{
public:
virtual void d2_func() = 0;
};
class D12B2 : public virtual D1, public virtual D2
{
public:
D12B2();
~D12B2();
virtual void d1_func()
{
// do something
}
virtual void d2_func()
{
// do something else
}
private:
int m_myData;
};
I have a quite special situation in my C++ program.
Look at the following class setup:
class Base1 {
public: void baseMethod();
}
class Base2 : public Base1 {
...
}
class Common {
public: void commonMethod();
}
class Derived1 : public Base1, public Common {
...
}
class Derived2 : public Base2, public Common {
...
}
Base1 and Base2 are unchangeable for me as they are part of a library.
What I want to achieve is that both Derived1 and Derived2 share the same method commonMethod(), so I use class Common with that method as a common base for Derived1 and Derived2.
The problem now is that commonMethod() shall contain a call to baseMethod() which is defined in Base1! In the context of a Derived1- or Derived2-object this is legal, but how to define that method in Common?
I know that if I would declare Base2 as virtual derived class from Base1 and the same for Common, it shouldn't be a problem (at least for Derived2, not sure about Derived1). But as I can't modify Base2 that's not possible anyway.
Also letting Common inherit from Base2 and then Derived1 and Derived2 solely from Common doesn't work because I don't want Derived1 to inherit from Base2!
What then came to my mind was to make a dynamic_cast within commonMethod():
void Common::commonMethod() {
...
Base1* self = dynamic_cast<Base1*>(this);
if(self) {
self->baseMethod();
}
...
}
This seems to work, but I'm not sure if this is a "nice" solution...
Do you have any ideas how to make it better? Or do you think this solution isn't bad at all? :)
If the only purpose of Common is to provide a common implementation of that one method, you can use the CRTP pattern and template it on the type of the base. At this point you could decide whether it makes sense to keep it as multiple bases of the DerivedX types or it could make sense to linearize the inheritance hierarchy:
// Option1
template <typename Derived>
struct Common {
void commonFunction() { ... static_cast<Derived*>(this)->foo(); ... }
};
struct Derived1 : Base1, Common<Derived1>
// Option2 (not strictly CRTP, but close)
template <typename Base>
struct Common : Base {
void commonFunction() { ... this->foo(); ... } // keep the this-> here
};
struct Derived1 : Common<Base1>
If I were you, I'd choose composition over multiple inheritance, i.e. to define common as a member object of derived classes.
class Base1 {
public: void baseMethod();
}
class Base2 : public Base1 {}
class Common {
public:
Common(Base1 *base): m_base(base) {}
void Common::commonMethod()
{
m_base->baseMethod();
}
private:
Base1 *m_base;
}
class Derived1 : public Base1
{
public:
Derived2(): m_common(this) {}
private:
Common m_common;
}
class Derived2 : public Base2
{
public:
Derived2(): m_common(this) {}
private:
Common m_common;
}
There is a potential risk of going this way though. Since member object(Common) is constructed first before the outer object(Derived1 or Derived2), you want to make sure no methods from the Derivedx object is called in Common's constructor.
I've got the following class structure:
class Common {
//members and data here.
};
class Derived1 : public Common
{
};
class Derived2: public Common, public Derived1
{
};
As I understand this hierarchy both Derived1 and Derived2 will share any members from Common.
Is there a way with out making Derived1 private in Derived2 to allow Derived2 to still inherit from Common but have separate function overrides.
Basically i need to override a virtual function in Derived1, and Derived2 but still have Derived1's function run (it's a threading api).
Any help apreciated.
As #Walkerneo points out, you don't need to inherit from both Common and Derived1. You can simply inherit from Derived1 and you'll also get inheritance from Common. You can explicitly call Derived1's method from Derived2's method by doing the following:
void Derived2::overriddenMethod ()
{
// Do something unique here
Derived1::overriddenMethod ();
// Maybe do some more stuff
}
You can achieve this even with single inheritance:
struct Base
{
virtual void foo() = 0;
virtual ~Base() { }
};
struct Intermediate : Base
{
virtual void foo() { /* ... */ }
// ...
};
struct Derived : Intermediate
{
virtual void foo()
{
Intermediate::foo();
// new stuff
}
};
Have you tried using virtual functions for runtime polymorphism and assigning a variable of your Derived2 class to a pointer of Derived1 class
class Common {
//members and data here.
public:
virtual void commonFunction() = 0; //keeping it pure virtual
};
class Derived1 : public Common
{
virtual void commonFunction(){
//do something in derived1
}
};
class Derived2: public Common, public Derived1
{
void commonFunction(){
//do something in derived2
}
};
int main(){
Derived2 derived2;
Derived1 *derived1;
derived1 = &derived2;
derived1->commonFunction(); //calls the common function definition in Derived1
/* ... */
}