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.
Related
I have a naive C++ inheritance class question. I have one base class Base, two derived classes DerivedA and DerivedB and two other distinct classes A and B which share the names of some methods.
Ideally I would like to design methods in the base class that use the methods of A and B. My attempt is the following
#include <cstdio>
class A{
public :
A(){};
void speak(){printf("hello A\n");};
};
class B{
public :
B(){};
void speak(){printf("hello B\n");};
};
class Base{
public:
Base(){};
void method(){property.speak();}
A property;
};
class DerivedA : public Base{
public:
using Base::Base;
A property;
};
class DerivedB : public Base{
public:
using Base::Base;
B property;
};
int main(int argc, char *argv[]){
DerivedA da;
DerivedB db;
da.property.speak();
db.property.speak();
// Attempting to call the shared method on the two distinct properties
da.method();
db.method();
}
Could you point me to a better design ? I suspect I should use templates but I am not sure how.
There are several options with different advantages and disadvantages.
You can make the base class a template like this:
template<class Property>
class Base{
public:
Base(){};
void method(){property.speak();}
Property property;
};
class DerivedA : public Base<A>{
};
class DerivedB : public Base<B>{
};
It is clear and simple, but notice that DerivedA and DerivedB in this case have no common base class, so you can't, e.g. put pointers to them in the same container.
You can use polymorphism.
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;
};
class DerivedA : public Base{
public:
A property;
void method() override { property.speak(); }
};
class DerivedB : public Base{
public:
B property;
void method() override { property.speak(); }
};
This is a bit more complex, involves some code duplication and requires more resources (to store virtual table e.g.), but now the classes really have a common ancestor.
Combine templates and polymorphism
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;
};
template<class Property>
class Derived: public Base {
public:
Property property;
void method() override { property.speak(); }
};
using DerivedA = Derived<A>;
using DerivedB = Derived<B>;
This is actually option #2, but with no code duplication: we make the compiler generate code for us using templates.
Other options. There may be other more specialized options depending on your requirements.
I have classes with inherits from other classes. I am looking for pattern which will allow me to break this type of class to class inheritance and use Interface instead.
For example:
Consider I have Base class and few derive classes as follows
Lib A :
class Base { ... }
Clients:
class Derived1 : public Base { ... }
class Derived2 : public Base { ... }
class Derived3 : public Derived2 { ... }
And clients uses objects of Base, Derived1, Derived2, Derived3.
I want to keep expose Base as interface.
Such that,
Lib A will contain:
Interface IBase ( exposed )
and Class BaseImpl ( internal )
And clients will use
class Derived1 : public IBase { .. }
class Derived2 : public IBase { .. }
class Derived3 : public IBase { .. }
Now problem is, if I make changes as above, I will loose default implementation provided by BaseImpl here.
1 possible solution that I could think of is having factory as:
Lib A:
Interface IBase { ... }
class BaseImpl : public IBase {
...
}
export static IBase* GetDefaultBase()
{
return new Base();
}
clients:
class Derived1 : public IBase
{
public:
Derived1() {
m_base = GetDefaultBase();
}
// and all implemented apis can use m_base to call default behavior provided by BaseImpl.
I dont see any issues with this approach. But I am curious to know, are there any well known pattern / solutions available for such refactoring problem?
Thanks,
Kailas
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();
}
};
Consider this example of code:
class Base
{
public:
Base() {}
};
class Derived1 : public Base
{
public:
Derived1() : Base() {}
};
class Derived2 : public Base
{
public:
Derived2() : Base() {}
};
Is there any to make that Derived1 has-a Derived2 and Derived2 has-a Derived1?
The best solution would be by using a third class which has those two objects. But in case high performance is needed?
An example might be a two-way client-server application.
EDIT: Consider that that's just a summary example. In the real code each of the three classes could throw an exception; I made sure that the code is exception-safe, though.
You can accomplish a "has-a" relationship with a forward declaration which basically tells "this class exists, it's just not declared yet"
#include <iostream>
using namespace std;
class Base
{
public:
Base() {}
};
// Forward declaration
class Derived1;
class Derived2 : public Base
{
friend class Derived1;
public:
Derived2() : Base() {}
private:
Derived1 *ptr;
};
class Derived1 : public Base
{
public:
Derived1(Derived2& obj) : Base(), ptr(&obj) {
obj.ptr = this;
}
private:
Derived2 *ptr;
};
int main() {
Derived2 obj2;
Derived1 obj1(obj2);
return 0;
}
http://ideone.com/RVU8AR
This way the two classes can communicate with each other. Notice the private pointers and the initialization into the constructor. With the "friend" declaration one class is able to modify the other class's private members.
Each class can hold a pointer:?
class Derived1
Derived2 *p_d2;
class Derived2
Derived1 *p_d1;
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
/* ... */
}