Hi all,
I have a number of classes which are very different from each other but have *some* shared functionality. For example, some of them have an identifier, some of them have a name, some of them have a description, etc. I've created Interfaces like "Identifiable," "Nameable," and "Describable" to pool the shared functionality. For instance:
1 2 3 4 5 6 7 8 9 10
|
class Nameable {
public:
Nameable(const std::string& name) : _name(name) {
}
const std::string& GetName() const {
return _name;
}
protected:
std::string _name;
};
| |
Then other classes can implement them. For instance, "items" have an id and a name, so I have:
1 2 3
|
class Item : public Identifiable, public Nameable {
//...
};
| |
Now I have a problem when I want to set two instances of a class which implements some of those interfaces equal to each other:
1 2 3 4
|
Item a(...);
Item b;
//...
b = a;
| |
The problem is I have to have the following code inside Item:
1 2 3 4 5 6
|
Item& operator=(const Item& cpy) {
_name = cpy._name; //Nameable
_id = cpy._id; //Identifiable
//Other copying stuff...
}
| |
I don't want to custom-tailor operator= for every different class depending on which interfaces it implements. I'd like to have the functionality of copying Nameable things inside Nameable, copying Identifiable things inside Identifiable, etc.
My attempted solution was to add an "operator=" to the interfaces:
1 2 3
|
Nameable& operator=(const Nameable& cpy) {
_name = cpy._name;
}
| |
Then I figured I could try to call those operators inside the Item operator= function as follows:
1 2 3 4 5 6
|
Item& operator=(const Item& cpy) {
*reinterpret_cast<Nameable*>(this) = cpy;
*reinterpret_cast<Identifiable*>(this) = cpy;
//Other copying stuff...
}
| |
Then the Item operator= still has to be custom-tailored depending on which interfaces it implements, but I figured it was still better because it was encapsulating the copying for each interface, so if I had a very complex interface with a lot of data then it would still be very simple to copy, and it would be good code reuse, and if I decided to change the interface later on then I wouldn't have to modify every single class which implemented it. Unfortunately my attempted solution doesn't work. Here's a compilable example which demonstrates why it doesn't work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
#include <iostream>
using namespace std;
class A1 {
public:
A1(int a) : a1(a) {}
A1& operator=(const A1& cpy) {
a1 = cpy.a1;
return *this;
}
int a1;
};
class A2 {
public:
A2(int a) : a2(a) {}
A2& operator=(const A2& cpy) {
a2 = cpy.a2;
return *this;
}
int a2;
};
class B : public A1, public A2 {
public:
B(int a1, int a2) : A1(a1), A2(a2) {}
B& operator=(const B& cpy) {
*reinterpret_cast<A1*>(this) = cpy;
*reinterpret_cast<A2*>(this) = cpy;
return *this;
}
};
int main(int argc, char* argv[]) {
B b1(5, 10);
B b2(0, 0);
b2 = b1;
cout << b2.a1 << ", " << b2.a2 << endl;
}
| |
I'd like it to output 5, 10, but instead it outputs 10, 0, because line 29 calls operator= from the A1 class. For this simple example where the type signatures match up, I end up with a neat (albeit wrong) answer. If I were to do this with my actual interfaces then I don't know what I'd get (garbage? memory access violation?).
Is there some sort of good solution to this problem (by which I mean, any way to have the functionality for copying inside the interfaces. I don't only mean a way to fix my specific failed solution, although that would work too) or will I just end up having to add copying code to all the classes that implement any of the interfaces?