klaus
klaus

Reputation: 826

c++ Getting access to member outside from inheritance chain

I have the following design: - one class A that has a protected member of class M. - one class B that inherits from A and has a pointer to an object of class C - one class C that needs to have access to the member of the class A

class A {
 public:
  A() : _member(0) {}
  ~A() { delete _member }
 protected:
  M _member;
}

class B : public A {
 public:
  B(){}
  ~B(){}
 protected:
  C* c;
}

class C {
  // C needs to have access to _member
}

What design should be more appropriate to solve this issue ?

Upvotes: 0

Views: 49

Answers (2)

Ian Young
Ian Young

Reputation: 1746

In pure OO terms, allowing a class to directly access the internal fields of another class is bad practice.

That said, C++ is not a pure OO language, and does allow for this (among other important deviations from OO).

To allow access to a private member to another class, you must designate that class to be a friend. Friendship, however is not passed to derived classes, therefore you must upcast the class to the type you need.

This is your simplest solution:

class A {
 public:
  A() : _member(0) {}
  ~A() { delete _member }
 protected:
  friend class C;
  M _member;
}

class B : public A {
 public:
  B(){ c = new C(this); } // this call will cast the B* to an A* (important)
  ~B(){ delete c;}
 protected:
  C* c;
}

class C {
public:
  C(A* a) { _a->_member = new M(); } //Now C can directly access _member in A
}

In such a way, any object derived from A can be turned back into an A* and used to access _member.

However, as previously stated, any classes derived from C will not gain access to _member, as friendship is not inherited, so a more comprehensive solution is required:

class M {
public:
    void Foo() { printf("Foo called\n"); }
};
class A {
    M* m;
    friend class C;
public:
    A():m(0) { ; }
};
class B :public A {
    int id;
public:
    B() { id = 0; }
};

class C {
public:
    C() { _a = 0; }
    C(A* a) { _a = a; }
protected:
    M* getM() { return _a->m; }
    void setM(M* m_) { _a->m = m_; }
private:
    A* _a;
};
class D : public C {
public:
    D(B* b): C(b) {
    }
    void Foo() {  
        setM(new M());
        getM()->Foo(); 
        delete getM();
        setM(nullptr);
    }
};

int main()
{
    B* b = new B();
    D d(b);
    d.Foo();
    delete b;
    getchar();
    return 0;
}

In this way, no classes derived from A provide direct access to _member, and no classes derived from C have direct access, but the member variable can still be accessed via C's protected API. This also prevents other external objects accessing it.

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234865

Make C a friend of A:

class A {
    friend class C;
    /*and so on*/

Then C can see all member variables and functions in A, even if they are private.

Upvotes: 1

Related Questions