Functions for every subclass combination - c++

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?

Related

Why doesn't 'using A::X' avoid ambiguity with multiple inheritance?

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(); }
};

using overloaded functions with polymorphic behaviour

I am implementing a generic work engine class that executes field-specific tasks. All fields shall be derived from a base class so polymorphic behavior will be used. I created overloaded functions with type-specific to derived fields, i.e work_engine::run(const a_field& af) in the below code. I've assumed whenever a field comes (the base class type), the appropriate function will be called automatically. However, I have got the error below (refers // magic line):
Error C2664 'void work_engine::run(const b_field &)': cannot convert argument 1 from 'base_field' to 'const a_field &'
I used to use this approach in C#, but I am not familiar with it in C++. By using C++11 and later features, I would like to implement the same approach, as it is cleaner code than using if-else statements with cast operations. On the other hand, perhaps I am doing primitive mistakes, so I'd like to separate my questions into two items:
What is the proper way of achieving my intention?
What is the origin of the error I've met?
Thanks in advance for all your comments,
Header1.h including class definitions is below:
#pragma once
#include <algorithm>
#include <list>
// abstract class of all fields
class base_field
{
public:
base_field() {}
virtual ~base_field() {}
};
// custom a field
class a_field : public base_field
{
public:
a_field() : base_field(){}
};
// custom b field
class b_field : public base_field
{
public:
b_field() : base_field() {}
};
class work_engine
{
public:
std::list<base_field> fields;
private:
void run(const a_field& af) {}
void run(const b_field& bf){}
public:
void run_all()
{
for_each(fields.begin(), fields.end(), [&](auto& el) { this->run(el); }); // magic line
}
};
An the main below:
#include <iostream>
#include <Header1.h>
int main()
{
work_engine engine;
engine.fields.push_back(a_field());
engine.fields.push_back(b_field());
engine.run_all();
}
In other words, what I am looking for is implicit cast to concrete class inside the lambda expression, referring to the // magic line.
First of all: You need a std::list<base_field *> as detailed in this question.
Secondly, downcasting must be done explicitly and you can't pick the appropriate function overload at runtime automatically.
One solution could be to use a (pure) virtual function on base_field
class base_field
{
public:
base_field() {}
virtual ~base_field() {}
virtual void Run() = 0;
};
// custom a field
class a_field : public base_field
{
public:
a_field() : base_field(){}
void Run(work_engine &engine) { engine.run(*this); }
};
There you either need to make work_engine::run public or make it a friend of a_field (or b_field respectivly).
The alternative would be to use type checking at runtime. If you have a base_field *base you can check the type like this:
auto aPtr = dynamic_cast<a_field *>(base);
if(aPtr != nullptr) {
this->run(*aPtr);
}
else {
auto bPtr = dynamic_cast<b_field *>(base);
if(bPtr != nullptr) {
this->run(*bPtr);
}
else {
// Ooops, it's something else entirely.
}
}
That's just a basic outline, but I hope it helps.
std::vector<std::unique_ptr<base_field>> fields;
if you want polymorphism don't use values. Also std list is a special case container in C++; use vector by default.
struct a_field;
struct b_field;
struct field_visitor{
virtual void operator()(a_field const&)=0;
virtual void operator()(b_field const&)=0;
};
template<class F>
struct visitor:field_visitor{
F f;
visitor(F in):f(in){}
virtual void operator()(a_field const& a){ f(a); };
virtual void operator()(b_field const& b){ f(b); };
};
class base_field {
public:
virtual void visit(field_visitor&)const=0;
// ...
class a_field : public base_field {
public:
virtual void visit(field_visitor& v){v(*this);}
//...
class b_field : public base_field {
public:
virtual void visit(field_visitor& v){v(*this);}
//...
void run_all() {
for_each(fields.begin(), fields.end(), [&](auto&& el) { if(el) el->visit( visitor{ [&](auto& field){this->run(field); } });});
}
there are a bunch of other ways to do this. (This one is c++17 but in a c++03 style).
Another option is to store a variant<a_field, b_field> and std::visit it. Another option is to write a runnable type erasure type.
std::vector<std::variant<a_field, b_field>> fields;
//...
void run_all() {
for_each(fields.begin(), fields.end(), [&](auto&& el) { std::visit( el, [&](auto&& x){ this->run(x); } ); });
}
the variant version is notable in that a_field and b_field need not be related types, just run has to accept them. So one could be std::string the other double.
C++ does not carry a complier around at run or link time (usually), so code at the point of use has to know what types it is written for. Vtable dispatch goes one way, and isn't extended due to requests outside of the class definition.
In comparison, C# carries a compiler around; so it can add a run dynamic dispatch based on two separate pieces of code automatically.
In C++, in double dispatch, one of the handled set of sub types should be listed. And in single dispatch, it needs be done within the type.
There are ways to stretch this, but not as far as C#.
I see using values instead of pointers cause object slicing: I changed values with pointers, shared_ptr in modern C++. The second, I moved run function into each field, so the field-specific function is encapsulated with the related field.
#pragma once
#include <algorithm>
#include <list>
// abstract class of base fields
class base_field
{
public:
base_field() {}
virtual ~base_field() {}
virtual void run() = 0;
};
// custom a field
class a_field : public base_field
{
public:
a_field() : base_field(){}
virtual void run() override{}
};
// custom b field
class b_field : public base_field
{
public:
b_field() : base_field() {}
virtual void run() override {}
};
class work_engine
{
public:
std::list<std::shared_ptr<base_field>> fields;
private:
public:
void run_all()
{
for_each(fields.begin(), fields.end(), [&](auto& el) { el->run(); });
}
};
With those changes, the error is disappeared as well as working as intended.

C++ Solving Diamond Inheritance Without Virtual Inheritance

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
}

access protected variable - complicated situation with inheritance and sub-classes

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.

Public and private access for the same member functions

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.