C++ class member visibility:

In C++, members of the "private:" section(s) of a class (or struct) definition are visible only within members of that class. Outside that class, they are inaccessible, and cannot be used. In effect, the scope of their declaration does not extend beyond the class -- and C++ won't let you use something with no declaration in scope!

The following code snippet shows some of the behaviour. Lines with comments starting "*" are compilation errors; since we're discussing visibility, we must show them.

class X {
private:
  int a;
  int square() {
    return a*a;            // OK (1)
  }
  X(const X& y);           // Code outside class cannot invoke
                           // copy constructor.
public:
  X(int val) : a(val) {}
  int& add(const X& y) {
    return a += y.a;      // OK (1)
  }
};

class Y : public X {
private:
  void print() {
    std::cout << a;        // * NOT OK (2)
  }
};


X quadruple(X x)           // * NOT OK (3)
{
  x.add(x);
  x.add(x);
  return x;                // * NOT OK (3)
}

void f() {
  X a(2);                  // OK (4)
  X b(3);
  X c(a);                  // * NOT OK (5)
  a.add(b);                // OK
  std::cout << a.a;        // * NOT OK (6)
  std::cout << a.square(); // * NOT OK (6)
}

Notes:

  1. A member function of X may access private: members. Note that visibility is phrased in terms of the class, not in terms of the object. Thus, X::add(const X&) can see not just its own a (this->a), but also y.a. There is no way (in C++) to prevent this: visibility is not related to instances.
  2. The class of Y is not the class of X. (Contrast this to the fact that an instance of Y is an instance of X!) private: members of X are not visible in Y. You need protected: for that.
  3. X has a private: copy constructor. So code outside it cannot pass X parameters, and cannot receive X return values. Thus, quadruple cannot be used. The implicit use of the copy constructor is enough to break it.

    If you must pass such an X to a function, you can use a reference, which requires no copy.

  4. You can create an X from an int using its public constructor.
  5. You also cannot explicitly call X's copy constructor.
  6. And, of course, direct access to X's private parts is forbidden.

The default visibility of a class is private: (this is the only difference between it and struct).

Finally, note that nested classes aren't "inside" their containing class; a class X::Foo would also be unable to use private members of X.

C++ inheritance visibility:

You may also declare an inheritance relation between two classes "private". It is very similar to private: visibility of members: only member functions of the class may use that inheritance. But of course, even they are bound by the visibility of the parent class' methods (just like Y was, in the previous example).

This is hardly "inheritance" in the sense of an "is-a" relationship, at least not outside the class. But that's the whole point: anything outside the implementation cannot tell (from external behaviour) that the inheritance exists. Thus, private inheritance is sometimes used to model a "has-a" relationship; it is unclear whether this offers any benefits over having a member of the appropriate type.