Reputation: 1254
I have the following class structure
class containingClass
{
int func1(int a);
containedClass containedClassObject;
}
I want to access func1
in containedClass
objects. What will be the best way to achieve that?
A naive solution that comes to mind is to pass a function pointer to the containedClass
's constructor, but then I get into a circular definition, as I need to pass a pointer to an object of the containingClass
as well.
Any suggestions?
Upvotes: 0
Views: 1484
Reputation: 35
Even if this already over a year old, I would like to help other seraching people.
Here is another example using a reference to the containing class. Tested with mingw32-g++ 4.9.2 and -std=c++98. Means it should work also with c++0x and c++11
#include <string>
#include <iostream>
using namespace std;
class clsDog;
class clsEar{
public:
clsDog& myDog;
clsEar(clsDog &dog);
};
class clsDog{
public:
clsEar ear;
void pain(string fromPart){
cout << "dog has pain in his " << fromPart << endl;
}
clsDog():ear(*this){};
};
clsEar::clsEar(clsDog &dog): myDog(dog){
myDog.pain("ear");
}
int main(){
clsDog dog;
}
First class clsDog
makes it available for reference and pointers. NOT for actual values like non reference member variables.
In class clsEar
a reference to clsDog
is created using clsDog& myDog
. The constructor can set the reference pointer in the initializer list. It is important that the containing class clsDog
is passed by reference otherwise the compiler tell you that the class incomplete.
Because clsEar
is now fully defined a normal member variable of clsEar
can be defined in clsDog
. Because clsEar
's constructor needs a reference to clsDog
it must be passed to it's constructor. This is done in the initialisier list of clsDog
's constructor by passing *this
.
Last but not least the implementation of clsEar::clsEar
must be done. It is necessary to do this after the complete definition of clsDog
to call the member functions or access member varibales of clsDog
in clsEar
. Otherwise the compiler will tell you again, that the class clsDog
is of incomplete type.
Upvotes: 0
Reputation: 30604
The containedClass
required a contract/API/function to be fulfilled by the int func1(int)
member of the containingClass
. Unless the containedClass
explicitly requires access to an instance of the containingClass
for other purposes, the access can be provided via lambda (or std::bind
) and the containedClass
can have a std::function
with the correct signature member that holds the lambda.
The only "trick" here would be to ensure that the lifetime of the objects are managed appropriately, i.e. the lifetime of the containingClass
instance is at least as long as required for use in the containedClassObject
object.
A sample;
#include <functional>
class containedClass {
std::function<int(int)> functor_;
public:
void setter(std::function<int(int)> functor) { functor_ = functor; }
};
class containingClass
{
int func1(int a);
containedClass containedClassObject;
public:
containingClass()
{
containedClassObject.setter([this](int a) -> int { return this->func1(a); });
}
};
Upvotes: 1