Roby wrote:[...] Sumankar but can you explain in plain and easy-to-understand English language? I don't get all your explanation

poor me....
<g>I wish I knew better.</g>I try to make up for my lack of knowledge with hard-to-understand phrases!
I'll give it a shot nevertheless: come back if you'd need further simplification. C++ happens to be an object
supporting langugage i.e. it allows you to write object-oriented code. Polymorphism, inheritance,
encapsulation are some of the facets of object oriented programming.[1] It is this inheritance that I'll
elaborate on a bit more for the purposes of explaining the fragment you posted sometime back.
Inheritance is, as the name suggests, a way to propagate (and perpetuate?) properties (state and behavior)
in a hierarchy. This is often what happens in a family -- common blood groups across father and son,
presdisposition towards Type 2 diabetes and the lot. Diagrammatically, it would look like any other
geneological tree:
Code: Select all
Grandfather [ class Base ]
| |
Father [ class Derived ]
/ \ / \
/ \ / \
/ \ / \
Son Daughter [ class DerivedDerived1 ] [ class DerivedDerived2 ]
In C++, this is done by deriving classes which has the syntax[2]:
Code: Select all
class Derived : <access_specifier> class Base {
<access_specifier_1>:
// some members
<access_specifier_2>:
// some more
...
<access_specifier_n>:
// few more
};
The access specifier is a sort of access control mechanism: when used in the class declaration,
it tells you what can be seen by people outside your family, what by people in your family (rather
children) and what can be seen by none other than yourself.
When used in to derive classes, access specifiers have a similar role: it tells you how much of the
base class is actually seen by the derived class. Here's a table for your aid:
Code: Select all
+------------------------------------------------------------------+
|mode\member | public | protected | private |
+------------------------------------------------------------------+
| public | All | Self & Children | None |
|------------------------------------------------------------------|
| protected | Self & Children | Self & Children | None |
|------------------------------------------------------------------|
| private | Self | Self | None |
+------------------------------------------------------------------+
Read the table like this: if derivation has mode <x> then a member of type <y> is visible by: cell[ x ][ y ]
All -- anyone
Self -- derived class only
Self & Children -- derived class & classes derived thereof
None -- not even the derived class
Now, let's take a look at the code I posted in response to your question:
Code: Select all
class Outer {
protected:
T Inner;
};
This declares a class Outer which has a variable of some type T which can be accessed by
member functions of class Outer and/or classes either publicly or protectedly derived from
Outer.
Now, let's take a look at your question:
Code: Select all
class Outer {
protected:
class Inner {
public:
int f();
};
};
class OuterBar : virtual public Outer {
public:
class InnerBar : virtual private Inner {
};
};
Inner is a nested class with protected access specifier -- so it can be seen by derived classes
and members of Outer. OuterBar is derived in public mode from Outer, so it has a protected member
called class Inner as well. Since f() is a public member of Inner, Inner::f(), is therefore a protected
member of class OuterBar. Its as if you wrote, instead:
Code: Select all
class OuterBar /* : virtual public Outer { */
protected:
class Inner {
public:
int f();
};
};
public:
class InnerBar /* : virtual private Inner {
public: */
private:
int f();
};
};
};
Note, that the
virtual keyword in this context only prevents classes derived from
OuterBar and say, OuterFoo (where OuterFoo is also derived from class Outer) from having duplicated
the base class part i.e. class Outer members.
Homework: what happens to the constructor of Inner in InnerBar?
Also, you absolutely MUST try out with as many compilers as you can and see how they react. G++
probably has options to get into a standard compliant mode, so you'll know if it's valid C++
syntax or not, as well. As for MS VC++ 6 -- I am doubtful, 7 and higher should behave okay.
HTH
---------
Suman
My Blog
My Website
Notes:
-------
[1] You can look up all of these concepts on the internet; it is beyond the scope of this post and/or my
capacity to explain in a few words

[2] This is a simplification: look up Stroustrup/internet for the C++ grammar
[3] A must read:
C++ FAQ