Nested Class member function can't access function of enclosing class. Why?

后端 未结 4 1673
不知归路
不知归路 2020-12-09 17:02

Please see the example code below:

class A
{
private:
    class B
    {
    public:
        foobar();
    };
public:
    foo();
    bar();
};
相关标签:
4条回答
  • 2020-12-09 17:26

    If you want to reuse functionality from A then you should inherit from A not nest B inside it.

    0 讨论(0)
  • 2020-12-09 17:27

    Basically what Georg Fritzsche said

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    class A
    {
    private:
        class B
        {
         A& parent_;
         public:
            //B();  //uncommenting gives error
            ~B();
            B(A& parent) : parent_(parent) {}
    
            void foobar() 
            { 
             parent_.foo();  
             cout << "A::B::foo()" <<endl; 
            }
    
            const std::string& foobarstring(const std::string& test) const 
            { 
             parent_.foostring(test); cout << "A::B::foostring()" <<endl;
            }
        };
    public:
        void foo();
        void bar();
        const std::string& foostring(const std::string& test) const;
        A(); 
        ~A(){};
        B b_;
    };
    
    //A::B::B() {}; //uncommenting gives error
    A::B::~B(){};
    
    A::A():b_(*this) {}
    
    
    void A::foo()
    {
        cout << "A::foo()" <<endl;
    }
    
    const std::string& A::foostring(const std::string& test) const
    {
        cout << test <<endl;
        return test;
    }
    
    void A::bar()
    {
        //some code
        cout << "A::bar()" <<endl;
        foo();
        //more code
    }
    
    int main(int argc, char* argv[])
    {
    A a;
    a.b_.foobar();
    a.b_.foobarstring("hello");
    
    return 0;
    }
    

    If you uncomment the default B constructor you would get an error

    0 讨论(0)
  • 2020-12-09 17:42

    foo() is a non-static member function of A and you are trying to call it without an instance.
    The nested class B is a seperate class that only has some access privileges and doesn't have any special knowledge about existing instances of A.

    If B needs access to an A you have to give it a reference to it, e.g.:

    class A {
        class B {
            A& parent_;
        public:
            B(A& parent) : parent_(parent) {}
            void foobar() { parent_.foo(); }
        };
        B b_;
    public:
        A() : b_(*this) {}
    };
    
    0 讨论(0)
  • 2020-12-09 17:47

    This is an automagic, albeit possibly nonportable trick (worked on VC++ since 6.0 though). Class B has to be a member of class A for this to work.

    #ifndef OUTERCLASS
    #define OUTERCLASS(className, memberName) \
        reinterpret_cast<className*>(reinterpret_cast<unsigned char*>(this) - offsetof(className, memberName))
    #endif 
    
    class A
    {
    private:
        class B
        {
        public:
            void foobar() {
               A* pA = OUTERCLASS(A, m_classB);
               pA->foo();
            }
        } m_classB;
    public:
        foo();
        bar();
    };
    
    0 讨论(0)
提交回复
热议问题