I have the following diamond class structure that does not compile:
class Base{
int a;
public:
virtual void doSomething();
};
class NotMineToTouch : public Base {};
class MyParentClass : public Base {};
class EvilDiamond : public NotMineToTouch, public MyParentClass {};
// I need these methods (that I cannot necessarily edit) to work for an EvilDiamond
void processBase (Base* b) { b->doSomething; /*...*/} // Cannot edit
void processParent (MyParentClass* p) { p->doSomething; /*...*/} // Can edit
void processNotMine (NotMineToTouch* n) { n->doSomething; /*...*/} // Cannot edit
I know the normal solution is to inherit virtually from Base; however, I am not allowed to change NotMineToTouch (or Base). Is there another solution? I am allowed to change MyParentClass and EvilDiamond at my pleasure; however, EvilDiamond must inherit from MyParentClass and NotMineToTouch, and MyParentClass must inherit from Base and may not inherit from EvilDiamond.
I challenge the following assertion:
EvilDiamond must inherit from MyParentClass and NotMineToTouch
You can probably do something along these lines (depending on your architecture):
class EvilDiamond;
class NotMineToTouchImpl : public NotMineToTouch {
EvilDiamond* tgt_;
public:
NotMineToTouchImpl(EvilDiamond* tgt) : tgt_(tgt) {}
... implement NotMineToTouch here, using tgt_ where you would have used this
};
class MyParentClassImpl : public MyParentClass {
EvilDiamond* tgt_;
public:
MyParentClassImpl(EvilDiamond* tgt) : tgt_(tgt) {}
... implement Base here, using tgt_ where you would have used this
};
class EvilDiamond {
friend class NotMineToTouchImpl;
friend class MyParentClassImpl;
// Creating permanent instances of the API classes
// may or may not be appropriate in your case.
NotMineToTouchImpl nmti_;
MyParentClassImpl pci_;
public:
EvilDiamond () : nmti_(this), pci_(this) {}
NotMineToTouchImpl* getAsNotMineToTOuch() {return &nmti_;}
MyParentClassImpl * getAsParentClass() {return &pci_;}
};
You don't have diamond as you don't use virtual inheritance.
you have some "Y" inheritance currently (EvilDiamond has 2 Base).
Without changing your classes, you may add overloads to instruct compiler what to do:
void processBase (EvilDiamond* evil) {
processBase(static_cast<NotMineToTouch*>(evil)); // Use NotMineToTouch::Base
processBase(static_cast<MyParentClass*>(evil)); // Use MyParentClass::Base
}
Related
I'm looking to have an vector of class instances which implement multiple virtual classes.
e.g.
// assume that all the classes here have implementations
class A
{
public:
virtual void doThing();
};
class ImplementsA
: public A
{
public:
void doThing() override;
};
class B
{
public:
virtual void doSomethingElse();
};
class ImplementsB
: public B
{
public:
void doSomethingElse() override;
};
class AB
: public A
, public B
{
public:
void doThing() override;
void doSomethingElse() override;
};
class OtherAB
: public A
, public B
{
public:
void doThing() override;
void doSomethingElse() override;
// these implementations are different than in AB
};
int main()
{
// here I'd like to have a vector of classes AB and OtherAB, and any other classes which implement both A and B
}
I've been poking around but I haven't found any information about how to do this. Is this possible in C++? If so, how would the vector be structured/initialized to allow it?
Thank you!
You need the Adapter and/or the Proxy and/or the Decorator design pattern. Try to wrap all the inheritance in ABwrapper : public A, public B
and create a vector of ABwrapper
class ABWrapper: public A, public B
{
public:
A *a; B *b; AB *ab;
void doThing()
{
if (this->ab==nullptr) {this->a->doThing(); return;}
this->ab->doThing();
}
void doOtherThing()
{
if (this->ab==nullptr) {this->b->doOtherThing(); return;}
this->ab->doOtherThing();
}
}
...
Vector<ABWrapper>
There are various ways to go about it:
Create a bundling interface, and manage your objects using pointers to them.
This runs counter to the interface-segregation-principle, and pre-supposes that you can modify all the affected classes.
Still, if you can do it and accept the drawback, it's the most efficient choice.
Save a pointer to each interesting interface.
If you need at most two interfaces, this is the second most efficient choice. Space use obviously increases linearly.
Write your own wrapper abstracting the differences away. See smart-pointer and std::function for ideas.
Use std::any and a map for registering how to access the interface. If few statically known fully derived types are involved, static functions might serve, and std::variant is enough.
This is similar to this question and this one, but I think (hope!) different enough to deserve an explanation.
I have a complex configuration framework, with decorator classes used to implement some common, simple actions (like flagging when a class Set accessor is called). I'm trying to introduce a new decorator (rather than a composition), which itself "should" inherit from that same common "Set-flagging" decorator.
I'm running into "ambiguous conversion from derived class to base class", and my attempts to work around it have failed.
I'm missing something obvious, I'm sure.
Here's a very simple example, without all my framework stuff.
class A {
public:
template <class T> void Set(T& arg, T val);
bool Ready() const;
};
class B : private A {
// Does stuff where I want to flag Set() actions
};
class C : public B, public A {
// This class needs the B interface, and the Set()-flagging
public:
void SetParam(double val) { Set(param, val); }
private:
double param;
};
Note that I original used virtual inheritance of A, but in practice I need to keep the "Set-flag" for B distinct from the "Set-flag" for C, hence my attempt above.
The private inheritance above was my first attempt to avoid the ambiguity. I also tried introducing using directives in C:
class C : public B, public A {
// This class needs the B interface, and the Set()-flagging
using A::Set;
using A::Ready;
};
This doesn't change the error. I understand from searching that the ambiguity is caught before the public/private state is checked. But I thought that the explicit using directives would resolve it. Why doesn't it? Do I need to go in and use A::Set(...) or A::Ready() explicitly everywhere?
Two solutions.
If you really want to keep the private and multiple inheritance:
class A {
public:
void Set() {};
bool Ready() const {};
};
class B : private A {
};
class C : public B, public A {
public:
void SetParam() { C::A::Set(); }
};
Or if that is not needed, then a simpler one:
class A {
public:
void Set() {};
bool Ready() const {};
};
class B : public A {
};
class C : public B {
public:
void SetParam() { Set(); }
};
I have the following setup:
class ComponentBase...
class A : public ComponentBase...
class B : public ComponentBase...
class C : public ComponentBase...
....
class ComponentOwner
{
public:
ComponentBase *b;
ComponentOwner(ComponentBase *newb) : b(newb) {};
bool couple(ComponentOwner *other)
{ //this in a non-header file, obviously
return couple(b, other->b);
};
....
}
There's overloaded functions for each combination of ComponentBase subclasses, that each return the same type and take the same sort of arguments, like this:
bool couple(A, A);
bool couple(A, B);
bool couple(B, A); //should point to couple(A,B)
....
Sadly this doesn't work, since I can't access the type of the ComponentBase pointer without knowing how to cast.
I guess my question is this: How would I go about redirecting two base pointers with unknown type to functions that are there for their type, with as little as possible extra definitions for the subclasses (like enums)?
Thanks.
EDIT 1:
It was proposed for me to add virtual functions, assuming to the ComponentBase.
class ComponentBase
{
public:
virtual bool couple(ComponentBase *other) = 0;
.....
}
class A : public ComponentBase
{
public:
bool couple(ComponentBase *other)
{
Do I understand the proposal right until here? How would I go about resolving the type of other?
Hmm... I'm trying to break down my problem...
There is a library with some classes that do almost what I want. I can't change classes of the library so I want to derive them and change what I need.
In this case there is a derived class in the library with two subclasses. Now I derive the class and the subclasses.
In the second sub-class there is a virtual method witch modifies a protected variable from the first sub-class.
I want to override the virtual method with a new virtual method which calls the old virtual wethod an then modify the protected variable again.
Why am I getting the error in mySubClass2 while accessing fResponse?
How can I solve my problem?
class libraryClass : pulic someLibraryBaseClass {
protected:
libraryClass::librarySubClass2 lookUpFunction(int ID) {
//some magic to find the obj
return obj;
}
public:
class librarySubClass2;
class librarySubClass1 {
public:
librarySubClass1(libraryClass baseObj) {
myBaseObj = baseObj;
}
void someCallingFunction(int ID) {
libraryClass::librarySubClass2 obj = myBaseObj->lookUpFunction(ID)
obj->someHandleFunction(this)
cout << fResponse;
}
protected:
friend class librarySubClass2;
unsigned char fResponse[200];
private:
libraryClass myBaseObj;
};
class librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
snprintf((char*)obj->fResponse, sizeof obj->fResponse, "Some Text...\r\n"
}
};
};
class myDerivedClass : public libraryClass {
public:
class mySubClass2 : public libraryClass::librarySubClass2;
class mySubClass1 : public libraryClass::librarySubClass1 {
protected:
friend class mySubClass2;
};
class mySubClass2 : public libraryClass::librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
libraryClass:librarySubClass2::someHandleFuntion(obj);
snprintf((char*)obj->fResponse, sizeof obj->fResponse, "Add some more Text...\r\n"
}
};
};
Edit: Forgot * in Method of mySubClass2
Possible solution:
class mySubClass2 : public libraryClass::librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
libraryClass:librarySubClass2::someHandleFuntion(obj);
myDerivedClass::mySubClass1* nowMyObj = (myDerivedClass::mySubClass*) obj;
snprintf((char*)nowMyObj->fResponse, sizeof nowMyObj->fResponse, "Add some more Text...\r\n"
}
};
Now I derive the class and the subclasses.
In your example code, you're only deriving the main class and not the subclass. You have to inherit also the subclass:
class libraryClass : pulic someLibraryBaseClass
{
class librarySubClass1 : public someLibraryBaseClass::someLibrarySubClass1 { };
// ....
};
But that can be done only if the subclass is accessible (protected/public).
As far as I can tell you wonder why you can't access obj->fResponse in
void mySubClass2::someHandleFunction(libraryClass::librarySubClass1 obj) { ... }
Well, obj is of type librarySubClass1 which inherits its share of fResponse from the common ancestor. However, that is the share of a relative of mySubClass2, not yours as you are mySubClass2! You can only access the fResponse member of objects which are known to be of type mySubClass which actually happens to be known to be not the case for a librarySubClass1 object.
Getting access to librarySubClass::fResponse is as if you got free access to your uncle's inheritance from your grandparents. Unless you have a very unusual family sharing its wealth freely among all family members, you probably won't have access to your uncle's inheritance either.
Because fResponse in mySubClass2 is treated as protected and at that point it is outside of libraryClass, it only worked on librarySubClass2 because it is inside libraryClass.
I have a class (class A) that is designed to be inherited by other classes written by other people.
I also have another class (class B), that also inherits from A.
B has to access some A's member functions that shouldn't be accessed by other inheriting classes.
So, these A's member functions should be public for B, but private for others.
How can I solve it without using 'friend' directive?
Thank you.
EDIT: Example why I need it.
class A
{
public:
void PublicFunc()
{
PrivateFunc();
// and other code
}
private:
virtual void PrivateFunc();
};
class B : public class A
{
private:
virtual void PrivateFunc()
{
//do something and call A's PrivateFunc
A::PrivateFunc(); // Can't, it's private!
}
};
You can't. That's what friend is for.
An alternative would be to change the design/architecture of your program. But for hints on this I'd need some more context.
What you say is: there are two sets of subclasses of A. One set should have access, the other set shouldn't. It feels wrong to have only one brand of subclasses (i.e. B) 'see' A's members.
If what you mean is: only we can use this part of functionality, while our clients can't, there are other resorts.
(Functionality reuse by inheritance often corners you with this kind of problems. If you go towards reuse by aggregation, you may get around it.)
A suggestion:
// separate the 'invisible' from the 'visible'.
class A_private_part {
protected:
int inherited_content();
public:
int public_interface();
};
class B_internal : public A_private_part {
};
class A_export : private A_private_part {
public:
int public_interface() { A_private_part::public_interface(); }
};
// client code
class ClientClass : public A_export {
};
But better would be to go the aggregation way, and split the current "A" into a visible and an invisible part:
class InvisibleFunctionality {
};
class VisibleFunctionality {
};
class B {
InvisibleFunctionality m_Invisible;
VisibleFunctionality m_Visible;
};
// client code uses VisibleFunctionality only
class ClientClass {
VisibleFunctionality m_Visible;
};
Well - if you want exactly what you've described, then friend is the best solution. Every coding standard recommends not using friend but where the alternative design is more complex - then maybe it's worth making an exception.
To solve the problem without friend will require a different architecture
One solution might be to use a form of the pImpl idiom where 'B' derives from the inner implementation object, while the other clients derive from the outer class.
Another might be to place an extra layer of inheritance between 'A' and the "other clients". Something like:
class A {
public:
void foo ();
void bar ();
};
class B : public A { // OK access to both 'foo' and 'bar'
};
class ARestricted : private A {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
However, this solution still has it's problems. 'ARestricted' cannot convert to an 'A' so this would need to be solved by some other "getter" for 'A'. However, you could name this function in such a way as it cannot be called accidentally:
inline A & get_base_type_A_for_interface_usage_only () { return *this; }
After trying to think of other solutions, and assuming that your hierarchy needs to be as you describe, I recommend you just use friend!
EDIT: So xtofl suggested renaming the types 'A' to 'AInternal' and 'ARestricted' to 'A'.
That works, except I noticed that 'B' would no longer be an 'A'. However, AInternal could be inherited virtually - and then 'B' could derive from both 'AInternal' and 'A'!
class AInternal {
public:
void foo ();
void bar ();
};
class A : private virtual AInternal {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
// OK access to both 'foo' and 'bar' via AInternal
class B : public virtual AInternal, public A {
public:
void useMembers ()
{
AInternal::foo ();
AInternal::bar ();
}
};
void func (A const &);
int main ()
{
A a;
func (a);
B b;
func (b);
}
Of course now you have virtual bases and multiple inheritance! Hmmm....now, is that better or worse than a single friend declaration?
I think you have a bigger problem here. Your design doesn't seem sound.
1) I think the 'friend' construct is problematic to begin with
2) if 'friend' isn't what you want, you need to re-examine your design.
I think you either need to do something that just gets the job done, using 'friend' or develop a more robust architecture. Take a look at some design patterns, I'm sure you'll find something useful.
EDIT:
After seeing your sample code, you definitely need to re-arch. Class A may not be under your control, so that's a little tricky, but maybe want you want to re-do Class B to be a "has-a" class instead of an "is-a" class.
public Class B
{
B()
{
}
void someFunc()
{
A a; //the private functions is now called and a will be deleted when it goes out of scope
}
};
I find this a interesting challenge. Here is how I would solve the problem:
class AProtectedInterface
{
public:
int m_pi1;
};
class B;
class A : private AProtectedInterface
{
public:
void GetAProtectedInterface(B& b_class);
int m_p1;
};
class B : public A
{
public:
B();
void SetAProtectedInterface(::AProtectedInterface& interface);
private:
::AProtectedInterface* m_AProtectedInterface;
};
class C : public A
{
public:
C();
};
C::C()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
B::B()
{
GetAProtectedInterface(*this);
// use m_AProtectedInterface to get to restricted areas of A
m_p1 = 0;
m_AProtectedInterface->m_pi1 = 0;
}
void A::GetAProtectedInterface(B& b_class)
{
b_class.SetAProtectedInterface(*this);
}
void B::SetAProtectedInterface(::AProtectedInterface& interface)
{
m_AProtectedInterface = &interface;
}
If you where going to use this sort of pattern all the time, you could reduce the code by using templates.
template<class T, class I>
class ProtectedInterfaceAccess : public I
{
public:
void SetProtectedInterface(T& protected_interface)
{
m_ProtectedInterface = &protected_interface;
}
protected:
T& GetProtectedInterface()
{
return *m_ProtectedInterface;
}
private:
T* m_ProtectedInterface;
};
template<class T, class I>
class ProtectedInterface : private T
{
public:
void SetupProtectedInterface(I& access_class)
{
access_class.SetProtectedInterface(*this);
}
};
class Bt;
class At : public ProtectedInterface <::AProtectedInterface, Bt>
{
public:
int m_p1;
};
class Bt : public ProtectedInterfaceAccess<::AProtectedInterface, At>
{
public:
Bt();
};
class Ct : public At
{
public:
Ct();
};
Ct::Ct()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
Bt::Bt()
{
SetupProtectedInterface(*this);
m_p1 = 0;
GetProtectedInterface().m_pi1 = 0;
}
If I understand:
A will be subclassed by other developers.
B will be subclassed by other developers and inherits from A.
A has some methods you don't want accessible to outside developers through B.
I don't think this can be done without using friend. There is no way I know of to make members of a superclass available only to direct inheritors.