Code (don't understand)

Write here if you have problems with your C++ source code

Moderator: Board moderators

Post Reply
Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Code (don't understand)

Post by Roby »

I got this from my friend (and I can't answer it :oops: )... I'm also interested with it (coz I'm not familiar with C++ code and these complicated codes seem interesting)... can someone explain to me? I also want to know if there are some resources for me to learn, not exactly same like these but at least nearly, about some complicated C++ code... I want to know more about this language.

Code: Select all

class Outer {
protected:
   class Inner {
   public:
       int f();
   };
};

class OuterBar : virtual public Outer {
public:
   class InnerBar : virtual private Inner {
   };
};
Question: Referring to the sample code above, what is the access level of member function Outer::Inner::f() from within the scope of class OuterBar::InnerBar?

Code: Select all

template<class T>
class Mapping
{
public:
   typedef T inner_type;
};

Mapping<int> m;
Question: Referring to the sample code above, which one of the following choices instantiates a variable, i, which is of the same type as the template parameter T used to instantiate the class of variable m?

thanx in advance :)

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Re: Code (don't understand)

Post by sumankar »

Code: Select all

class Outer {
protected:
   T Inner;
};
How would you read this for some type T? Think about access
qualifiers. I have't come across anything that says it should be
anything else when it comes to a nested class. I might be wrong ;)
so prove me wrong. Also, the forget the `virtual' in the next part
and see if you can understand it! Come back if you've more questions.
Question: Referring to the sample code above, which one of the following choices instantiates a variable, i, which is of the same type as the template parameter T used to instantiate the class of variable m?
Did you miss something here :D ?

HTH
---------
Suman
My Blog

Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Re: Code (don't understand)

Post by Roby »

sumankar wrote:

Code: Select all

class Outer {
protected:
   T Inner;
};
How would you read this for some type T? Think about access
qualifiers. I have't come across anything that says it should be
anything else when it comes to a nested class. I might be wrong ;)
so prove me wrong. Also, the forget the `virtual' in the next part
and see if you can understand it! Come back if you've more questions.
Question: Referring to the sample code above, which one of the following choices instantiates a variable, i, which is of the same type as the template parameter T used to instantiate the class of variable m?
Did you miss something here :D ?

HTH
---------
Suman
My Blog
Sumankar, I really didn't understand those codes... it's so complicated! AFAIK, the virtual keyword within inheritance is to solve multiple inheritance problem, so there's only one object for base class. Is there anything else?

And the second question, yah... it's unclear because my friend didn't give me the multiple choices, and he also forgot to take the multiple choices from the source. Refer to sample code in second question, would you mind if you give some correct ways to instantiate the object?

Thanx in advance...

PS: sorry Sumankar but can you explain in plain and easy-to-understand English language? I don't get all your explanation :oops: poor me....

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Re: Code (don't understand)

Post by sumankar »

Roby wrote:[...] Sumankar but can you explain in plain and easy-to-understand English language? I don't get all your explanation :oops: 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

Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby »

I'm using Borland C++ 3.1 to compile the first one, and I got these output:

Code: Select all

Outer running...
OuterBar running...
Inner running...
InnerBar running...
InnerBar destroyed...
Inner destroyed...
OuterBar destroyed...
Outer destroyed...
The code that I modified:

Code: Select all

#include <iostream.h>

class Outer {
public:
   Outer() { cout << "Outer running...\n"; }
	~Outer() { cout << "Outer destroyed...\n"; }
	void make() { Inner in; }
protected:
	class Inner {
	public:
		 int f();
		 Inner() { cout << "Inner running...\n"; }
		 ~Inner() { cout << "Inner destroyed...\n"; }
	};
};

class OuterBar : virtual public Outer {
public:
	OuterBar() { cout << "OuterBar running...\n"; }
	~OuterBar() { cout << "OuterBar destroyed...\n"; }
	void make() { InnerBar in; }
	class InnerBar : virtual private Inner {
		public:
			InnerBar() { cout << "InnerBar running...\n"; }
			~InnerBar() { cout << "InnerBar destroyed...\n"; }
	};
};

void main()
{
 OuterBar out;
 out.make();
}
So from my observation above, the Inner constructor only once running... is that correct? (I hardly try to understand these complicated codes, I hope I'm not wrong :roll: )
Why it's only once running, because like you said before, the virtual keyword can make sure the base class only once build and so only one object of base class can be created at that time, is that correct?

I tried compile it with MS Visual C++ 6 and I got error and so does GCC in linux. I didn't understand why I success compile it within my Borland C++ 3.1 compiler. :oops: confused mode on :oops:

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar »

Roby wrote:[...]Why it's only once running, because like you said before, the virtual keyword can make sure the base class only once build and so only one object of base class can be created at that time, is that correct?
Because there is no object of type inner created when an object of type OuterBar is created.Forget the virtual stuff. OuterBar is derived from Outer (and both ctors are being called).The base class has declared a nested class but does not have a member object of type Inner. However, in OuterBar::make() (which has overriden the base class's implementation -- should always use a virtual before function declaration in base) an object of type InnerBar is created. In order to create InnerBar object, Inner ctor is called (base class ctor called before derived class ctor). Destruction is in reverse order of construction. Hence what you see is what you get :)
I tried compile it with MS Visual C++ 6 and I got error and so does GCC in linux. I didn't understand why I success compile it within my Borland C++ 3.1 compiler...
MSVC++ 6 has a problem with this particular construct, see msdn. They have a queer way of getting around this. Also, gcc is probably in C mode, use g++ instead or simply c++. Getting gcc to work with C++ should be possible with the -x option and some other dark art I am not even aware of ;)

Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby »

Thanx Sumankar for your explanation...
sumankar wrote:Because there is no object of type inner created when an object of type OuterBar is created.Forget the virtual stuff. OuterBar is derived from Outer (and both ctors are being called).The base class has declared a nested class but does not have a member object of type Inner.
Ooopss, ya, you right... because there's no inner object in the base class when the OuterBar object is created.
sumankar wrote:However, in OuterBar::make() (which has overriden the base class's implementation -- should always use a virtual before function declaration in base) an object of type InnerBar is created.
Why should I declare virtual before the function prototype? I didn't understand... Isn't it the way to make polymorphism code? I don't get your explanation in this part :oops:

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar »

Roby wrote:[...]Why should I declare virtual before the function prototype? I didn't understand... Isn't it the way to make polymorphism code? I don't get your explanation in this part
The keyword virtual is required to get the correct function called when function calls are made via a base class pointer. In your code you have the derived class overriding the base class member function make(). However, the effect of this gets lost when a pointer to the base class is used to call the function make().

Run the following and try to analyze why the outputs are the way they appear on your screen ;) And of course, try it with and without setting a macro called PROPER and find out why you get differences.

Code: Select all

#include <iostream>
class B { 
public:
#ifdef PROPER
      virtual
#endif
      void f() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};

class D : public B { 
public: 
      void f() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};

void foo(B* pB) {
       std::cout << __PRETTY_FUNCTION__ << "\n";
       pB->f(); 
}

int main()
{
  std::cout << __PRETTY_FUNCTION__ << "\n";
  B b; 
  b.f();
  D d;
  d.f();
  B *bp = new B;
  bp->f();
  D *dp = new D;
  dp->f();
  B *p = new D;
  p->f();
  foo(bp);
  foo(dp);
  fpp(p);
  delete bp; 
  delete dp;
  delete p;
}

Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby »

Hmmm... still confused why... from your given code (I've compiled it with MS Visual with some modification on codes) I got different results like you said... hmm... PROPER isn't keyword in C++, is it?

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar »

Roby wrote:Hmmm... still confused why... from your given code (I've compiled it with MS Visual with some modification on codes)
I have not seen the modified code -- so can't comment. Also, VC++ 6 is not something I am very familiar with, so it would be unwise to give you misleading info. But there were a few issues with their C++ implementation AFAIR. So, consult the proper documentation or post in usenet (a msdn specific newsgroup) probably or wait here for someone to come up with the correct answer ;)
I got different results like you said... hmm... PROPER isn't keyword in C++, is it?
Re-read my post. Here's the answer:
sumankar wrote:[...]And of course, try it with and without setting a macro called PROPER and find out why you get differences. [...]
Here's a bit of advice: you really need a book. This forum cannot replace a good book. Read Stroustrup, get it from your library or whatever, but read it first and then if you hit something, you can always come back.

Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby »

sumankar wrote:
Roby wrote:Hmmm... still confused why... from your given code (I've compiled it with MS Visual with some modification on codes)
I have not seen the modified code -- so can't comment. Also, VC++ 6 is not something I am very familiar with, so it would be unwise to give you misleading info. But there were a few issues with their C++ implementation AFAIR. So, consult the proper documentation or post in usenet (a msdn specific newsgroup) probably or wait here for someone to come up with the correct answer ;)
I got different results like you said... hmm... PROPER isn't keyword in C++, is it?
Re-read my post. Here's the answer:
sumankar wrote:[...]And of course, try it with and without setting a macro called PROPER and find out why you get differences. [...]
Here's a bit of advice: you really need a book. This forum cannot replace a good book. Read Stroustrup, get it from your library or whatever, but read it first and then if you hit something, you can always come back.
ya... you right... may be I need book to understand those... and I guess my library doesn't have stroustrop (this just my guess). Does Deitel C++ How To Program a good book? I've seen those a lot in my college library.

About the modification code I made, I just replaced _PRETTY_FUNCTION_ with some string, example "asdf" just in case to know what happen with the constructor (this is my approach to understand the code).

thanx Sumankar... at least I know a little C++ rich mistery from these... :)

Roby
Experienced poster
Posts: 101
Joined: Wed May 04, 2005 4:33 pm
Location: Tangerang, Banten, Indonesia
Contact:

Post by Roby »

One question more Sumankar... can a template class be inherited? If it can, how? I just wanna know if it's can coz I try a lot but always got error... :oops:

sumankar
A great helper
Posts: 286
Joined: Tue Mar 25, 2003 8:36 am
Location: calcutta
Contact:

Post by sumankar »

Roby wrote:[...]and I guess my library doesn't have stroustrop (this just my guess). Does Deitel C++ How To Program a good book? I've seen those a lot in my college library.
Never read that one. So no comments.However, do have a look here. Also check out amazon etc for reviews. It'd be the very strange if your college library doesn't have Stroustrup. Ask your prof to get at least 1000 copies of that book ;) -- its worth it.
Roby wrote: About the modification code I made, I just replaced _PRETTY_FUNCTION_ with some string, example "asdf" just in case to know what happen with the constructor (this is my approach to understand the code).
_PRETTY_FUNCTION_ would infact tell you which function you are in, in a nicely formatted way. __FUNCTION__ isn't as nice. And they are standard macros. So you should be able to use them anywhere. Also try out the online book by Bruce Eckel, that's not too bad I guess.

As for template class inheritance -- don't be so lazy! GIYF. STFW ;)

Post Reply

Return to “C++”