0

In a project, I have a class hierarchy implementing a graph with levels of hierarchy (that is, a graph node can be a graph itself — think of it as an electronic circuit where a gate can actually be an integrated chip, for instance). Thus, I have some class Base derived into Group and Leaf, and the class Base has an attribute ancestor, which I would like to be able to set from a given method of Group (when adding a child), but not from anywhere else:

class Group;

class Base {
    private: // or protected?
        Group* ancestor;
};

class Group : public Base {
    private:
        void setAncestor(Base* child) {
            // Something like
            child->ancestor = this;
        }
};

class Leaf : public Base {
    // ...
};

What would be the "correct" way to achieve that? Usually, I would use friend methods, but it seems to me that this is impossible in this context, since I would have to declare friend Group::setAncestor in Base, which must be declared before. (Also note that those declarations are in different files in the real code.)

tobast
  • 101
  • 4
  • This doesn't work unless `ancestor` is public. `Group` can access protected members of *its own* base class. It can not access protected members through `Base` pointers, as these might be bases of some unrelated class, like `Leaf`. – Bo Persson Mar 27 '17 at 15:25
  • 1
    You might make the whole class friend, i.e. `friend class Group;`. – songyuanyao Mar 27 '17 at 15:25
  • You could use forward declaration and `friend`. – Raito Mar 27 '17 at 15:49

2 Answers2

0

data member Base::ancestor should have protected access. That way it will be available to derived classes.

shargors
  • 2,147
  • 1
  • 15
  • 21
0

You can declare it as protected in Base, and in the Leaf class and from anywhere else use private inheritance, so protected members will be private.

class Group;

class Base {
    protected:
        Group* ancestor;
};

class Group : public Base {
    private:
        void setAncestor(Base* newAncestor) {
            // Something like
            ancestor = newAncestor->ancestor;
        }
};

class Leaf : private Base {
    // ...
};

Note that I change the name from child to newAncestor.

So when you create a new child you can do something like this:

Base ancestor;
Group child;
child->setAncestor(&ancestor)
Rama
  • 3,222
  • 2
  • 11
  • 26
  • It won't have the same effect. – O'Neil Mar 27 '17 at 16:12
  • @O'Neil Off course `setAncestor()` has a different signature in my example. Just a suggestion. But I'm not sure if that's what you're referring to. – Rama Mar 27 '17 at 16:15
  • Yes this is it. The point is to have `ancestor` to point to **another** instance. Not `this`. – O'Neil Mar 27 '17 at 16:54