Reputation: 9527
I have this structures in C++11
struct A {
int idA;
void setId(int i) { idA = i;}
int getId() { return idA;}
virtual void foo() = 0;
};
struct B {
int idB;
void setId(int i) { idB = i;}
int getId() { return idB;}
virtual void foo2() = 0;
};
struct AB : public A, public B
{
void foo() override {}
void foo2() override {}
};
Now in main I can call it like this:
AB * ab = new AB();
ab->B::setId(10);
but I dont really like it.
Is there any other solution? Methods setId/getId
from struct A
are not needed in AB
. I just did the inheritance, because I need foo()
and other stuff from A
, but all other methods are unique.
Upvotes: 16
Views: 21922
Reputation: 352
The accepted answer does work as long as you call setId(int)
on an object of type AB or an AB pointer (most cases, surely). But if you want to call the function on A* ab = new AB();
you have to explicitly override it.
struct A {
int idA;
virtual void setId(int i) { idA = i;}
};
struct B {
int idB;
virtual void setId(int i) { idB = i;}
};
struct AB : public A, public B
{
void setId(int i) override { B::setId(i); }
};
Upvotes: 5
Reputation: 300
Typically with OO and Inheritance, if functionality reuse is unknown at the time, it is typically better to implement the function several times until you determine a pattern that will allow you to break it apart.
For instance, there is nothing wrong with having a class object being a container of data and inherriting from it.
class IdentificationData {
int ID;
. . .
}
You also do not necessarily need to have functions be part of a class. A class is simply a container, and is used to organize and encapsulate data, functions that may operate on the data, or a collection of functions into one common set.
class IdentificationFunctionality{
static SetID( IdentificationData* obj) {...}
}
Doing this will then allow you to do something like...
class AB: IdentificationData, B {
. . .
}
AB* ab = new AB();
IdentificationFunctionality::SetID(&ab);
The other benefits to this, is this will allow you to do some book keeping without your objects needing to know the details of the data-banking system.
Upvotes: 0
Reputation: 4106
I believe that both mine and the accepted answers introduces rather annoying problem, consider:
AB ab;
A *a = &ab;
a->setId(10); //problem
a->foo(); //calls AB::foo() correctly
When the name hiding is used (accepted answer) the AB
object never gets called while my answer (wrapping the call) does not account for this either. The correct approach in this case in my opinion is to use private
inehritance of A
and exposing only foo()
, so only one thing would change from original OP's code:
struct AB : private A, public B
Upvotes: 2
Reputation: 4106
What about wrapper forwarding methods:
struct AB : public A, public B
{
public:
void setAId(int i) { A::setID(i); }
void setBId(int i) { B::setID(i); }
};
That way you do not become "victim" of name hiding, your intent becomes clear in the code and you have the names that reflect what they do and you do not need to access the member(s) of base class(es) explicitely.
Alternatively you can create another base class and inherit it virtually in both A
and B
in which you would contain the setId
method.
Upvotes: 9
Reputation: 1125
Since you said that you don't need A
's version of those methods, you could write
struct AB : public A, public B
{
void foo() override {}
void foo2() override {}
using B::setId;
using B::getId;
};
This will put B
's implementation of those methods into AB
's namespace and make calling them unambiguous.
Upvotes: 23