问题
After writing a test, I determined that the this
pointer in an interface is not equal to the this
pointer of the concrete class, meaning I can't just use a C-style cast on it.
class AbstractBase {...};
class AnInterface {
public:
AnInterface() {...} // need AbstractBase * here
~virtual AnInterface() {...} // and here
};
class Concrete : public AbstractBase, public AnInterface {};
My interface needs a base class pointer to the concrete class inheriting it in the constructor and destructor in order to handle interface related registration and deregistration.
Every concrete object that inherits the interface needs to inherit the abstract base class first, it is always first in the layout.
For the constructor it is not all that hard, I can add a pointer in the interface constructor and pass this
from the concrete class. But the destructor doesn't have any parameters, so I am in the dark there.
The solutions I came up with so far come with overhead:
1 - store the pointer in the interface to be used in the destructor - adds in one pointer worth of memory overhead
class AnInterface {
public:
AnInterface(AbstractBase * ap) {...}
~virtual AnInterface() {...} // and here
private:
AbstractBase * aPtr;
};
...
Concrete() : AnInterface(this) {}
2 - create an abstract method in the interface and implement it to return this
in the concrete class - adds in the overhead of indirection for the virtual call
class AnInterface {
virtual AbstractBase * getPtr() = 0;
};
class Concrete : public AbstractBase, public AnInterface {
AbstractBase * getPtr() { return this; }
};
3 - dynamic_cast
is even worse
Is there a more efficient way to achieve this?
回答1:
IMO if decoupling between the base class and the interface is really needed, both solution 1 and 2 have tolerable overheads, certainly nothing that will be a problem on contemporary hardware.
But since you say that the interface is designed to work with the functionality, provided in the base class, then maybe the decoupling is not a good thing.
I mean if the problem is with inheriting multiple interfaces which all inherit the base class, or the "dreaded diamond" problem with inheritance, you can simply use virtual inheritance.
回答2:
All of your concerns seem like micro-optimizations. Assuming you truly can't separate out your interface from your implementation (in which case, why are you using interfaces in the first place?) I would just use dynamic_cast
and be done with it, even though it's pretty heavyweight. If I were stuck on a platform where RTTI isn't an option then I'd use option 2.
回答3:
Your design has some flaws.
You should consider using CRTP as from the Mixin aspect, which saves you from keeping an extra pointer of the concrete derived.
template<typename Derived>
class AnInterface {
public:
AnInterface() {
Derived* derived = static_cast<Derived*>(this);
AbstractBase* abstractBase = static_cast<AbstractBase*>(derived);
} // have AbstractBase * here
~virtual AnInterface() {...} // and here
};
class Concrete
: public virtual AbstractBase
, public AnInterface<Concrete> {
AbstractBase * getPtr() { return this; }
};
来源:https://stackoverflow.com/questions/29085834/access-this-pointer-of-concrete-class-from-interface