Identical methods/properties in separate interfaces ?
-
Hi all, ATL question: suppose I have two interfaces (IFirst, ISecond), and both interfaces have a method Test(). Now I would like to implement both IFirst and ISecond in a single object, but still have two separate implementations of the Test() method. Any pointers on how this can be done ? Thanks, Alwin
-
Hi all, ATL question: suppose I have two interfaces (IFirst, ISecond), and both interfaces have a method Test(). Now I would like to implement both IFirst and ISecond in a single object, but still have two separate implementations of the Test() method. Any pointers on how this can be done ? Thanks, Alwin
-
Hi all, ATL question: suppose I have two interfaces (IFirst, ISecond), and both interfaces have a method Test(). Now I would like to implement both IFirst and ISecond in a single object, but still have two separate implementations of the Test() method. Any pointers on how this can be done ? Thanks, Alwin
What you may have to do is what's sometimes called forwarding shims. The trick is to "prebind" the virtual methods. Observe:
class IFirstFwd : public IFirst {
public:
HRESULT Test() {
return IFirst_Test();
}virtual HRESULT IFirst\_Test() = 0;
};
class ISecondFwd : public ISecond {
public:
HRESULT Test() {
return ISecond_Test();
}virtual HRESULT ISecond\_Test() = 0;
};
class CYourComClass : public IFirstFwd, public ISecondFwd {
public:
HRESULT IFirst_Test() {
...
}HRESULT ISecond\_Test() { ... }
};
I know it looks clumbsy, but since C++ does not have a feature for renaming inherited methods, this is the most type safe way to do it. Ok, so know that you know how it works, let's cut off those extra 8 bytes from the vtable (on wintel ia32) by adding templates:
template <typename T>
class IFirstFwd : public IFirst {
public:
HRESULT Test() {
return static_cast<T*>(this)->IFirst_Test();
}
};template <typename T>
class ISecondFwd : public ISecond {
public:
HRESULT Test() {
return static_cast<T*>(this)->ISecond_Test();
}
};class CYourComClass : public IFirstFwd<CYourComClass>, public ISecondFwd<CYourComClass> {
public:
HRESULT IFirst_Test() {
...
}HRESULT ISecond\_Test() { ... }
};
There is another way - although not very pretty IMHO. It will only work well once the interfaces have finalized. I.e., this is very bad during development, because you lose all the help from the type system, and the bugs you may potentially have will be less than fun to figure out:
class ISecondFake {
// Copy the methods from ISecond and past it here
// Prefix all mthods with ISecond_
virtual __stdcall HRESULT ISecond_Test() = 0;
};class CYourComClass : public IFirst, public ISecondFake {
public:
HRESULT Test() { // IFirst version
...
}HRESULT ISecond\_Test() { ... }
};
This'll work as long as your ISecondFake is vtable-compatible with ISecond. But should you change the vtable layout or method signature of ISecond in any way, don't forget to update ISecondFake or you'll be in for quite the ride.. :) -- Gott weiß ich will kein Engel sein.