简体   繁体   中英

How should I access a function of a container class in a contained class object

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?

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, ie 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); });
    }
};

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM