Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A problem in C++

2 views
Skip to first unread message

N. Maheswaran

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

hello,

My name is Maheswaran N. I am working for a company called Siemens
Information Systems Ltd., Bangalore, India. We develop medical
application in C++.

I have a problem(taken from Copliens book).
I have discussed this problem in our company's c++ newsgroup
and i could not get an answer. So I thought I will post it here

The problem is:

Consider the following piece of code.

/******************** BEGIN **********************/

#include <iostream.h>

class Telephone
{
public:
~Telephone(){}

protected:
Telephone(){}
};
class ISDNPhone : public Telephone
{
public:
ISDNPhone(){ Telephone t; }
~ISDNPhone(){}
};
void main()
{
ISDNPhone t;

}


/***************** END ************************************/

Here, the base class constructor is protected. And I am trying to
instantiate a base class object in a derived class constructor.
The above piece of code is compiling in some compilers and not compiling

in some others. But I dont know why??

I tried compiling the above code in MSVC++4.2, g++(version 2.8.0) and
CC of Sun Sparc( version 3.0.1 ).
It did not compile in MSVC++4.2 and g++. But it compiled in
CC of Sun Sparc.

In our internal newsgroup I got the answer that
" Since the constructor of the base class is protected, it cannot
be instantiated anywhere even in a derived class's method."

This argument is quite reasonable. Even I support this. But Coplien
in his book( page 104 ) says,
"Actually, the protection against making an object of type Telephone
is not perfect here: One can be created in member functions of any
subclass of Telephone, or in any 'friend' functions of class
Telephone if such should exist".

According to this statement, the above code should compile.
Now what I want to know is, which is correct out of the above
two arguments.

In short, should the above code compile or not???
If not, then is Coplien wrong or is it that I have interpreted wrongly??

If yes, then is it that the Sun Sparc compiler is wrong??

Please reply,
Thanks in advance,
Maheswaran N.


Michael J. Tobler

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <355025EB...@blr.sni.de>, ma...@blr.sni.de said...
[snip]
By the way, VC++ 5.0 gives the same error. A section of their error
documentation states:
"This error can be caused by attempting to access a member that is
declared as private or protected, or by accessing a public member of a
base class that is inherited with private or protected access."

Funny how they "lump" protected with private in thier desciption.

I'd have to say the compilers giving you an error are incorrect. From
Stroustrup (C++ Programming Language, 3rd Edition, p.404:
"A derived class can access a base class' protected members only for
objects of its own type."

> #include <iostream.h>
> class Telephone
> {
> public:
> ~Telephone(){}

Be sure your destructor is virtual:
virtual ~Telephone(){}


> protected:
> Telephone(){}
> };
> class ISDNPhone : public Telephone
> {
> public:
> ISDNPhone(){ Telephone t; }
> ~ISDNPhone(){}

Be sure your destructor is virtual:
virtual ~ISDNPhone(){}
> };
> void main()
This NEEDS to be: int main().
"main()" returns an int, if declared any other way, it is undefined
behaviour. Do not do this.

> {
> ISDNPhone t;
>
return 0 ;


> }
>
>
> /***************** END ************************************/
>
> Here, the base class constructor is protected. And I am trying to
> instantiate a base class object in a derived class constructor.
> The above piece of code is compiling in some compilers and not compiling
>
> in some others. But I dont know why??
>
> I tried compiling the above code in MSVC++4.2, g++(version 2.8.0) and
> CC of Sun Sparc( version 3.0.1 ).
> It did not compile in MSVC++4.2 and g++. But it compiled in
> CC of Sun Sparc.
>
> In our internal newsgroup I got the answer that
> " Since the constructor of the base class is protected, it cannot
> be instantiated anywhere even in a derived class's method."
>
> This argument is quite reasonable. Even I support this. But Coplien
> in his book( page 104 ) says,
> "Actually, the protection against making an object of type Telephone
> is not perfect here: One can be created in member functions of any

--
<<<<<<<<<< Blue Skies >>>>>>>>>>>
* Michael J. Tobler *
* mto...@no-spam-ibm.net *
* remove "no-spam-" when replying *
***********************************

Jawed Karim

unread,
May 6, 1998, 3:00:00 AM5/6/98
to N. Maheswaran

Phlip

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

<cross-posted to the moderated newsgroup against potential blandishments
or
emendments>

N. Maheswaran wrote:

>I have a problem(taken from Copliens book).
>I have discussed this problem in our company's c++ newsgroup
>and i could not get an answer. So I thought I will post it here

>#include <iostream.h>
>
>class Telephone
>{
> public:
> ~Telephone(){}
>


> protected:
> Telephone(){}
>};
>class ISDNPhone : public Telephone
>{
> public:
> ISDNPhone(){ Telephone t; }
> ~ISDNPhone(){}

>};
>int main()
>{
> ISDNPhone t;
>
>}

>Here, the base class constructor is protected. And I am trying to
>instantiate a base class object in a derived class constructor.

>The above piece of code is compiling in some compilers...


The only thing you can do is inherit the class 'Telephone' and then
construct yourself. No locals or members permitted.

This line constructs a 'Telephone' that is not yourself - it's a local
object:

ISDNPhone(){ Telephone t; } // error

You are allowed to use sub-constructor notation, but if you really want
a
local you must change the access requirements:

ISDNPhone(): Telephone () { } // okay

>But I dont know why??

A good rule of thumb is that 'protected' reduces all permissions to
anything
that could be expressed as:

this->expression;

That is an excellent rule of thumb, but it instantly breaks down for
anything for which you already cannot say 'this->', like static members,
types, constructors, etc.

By contrast, you definitely cannot do this:

void Class::function (Class &that)
{
that.protectedMember;
}

You are not using 'this', so you can't get to the member.

>This argument is quite reasonable. Even I support this. But Coplien
>in his book( page 104 ) says,
>"Actually, the protection against making an object of type Telephone
>is not perfect here: One can be created in member functions of any

>subclass of Telephone, or in any 'friend' functions of class
>Telephone if such should exist".

These are wrong.

C++ is awesome, but you simply cannot create an object that "can be
constructed here, but can't be constructed anywhere I don't want." Your
choices are either to use protection, or to make the constructor private
and
befriend the derived class. Each of these has various trade-offs.

Remember that encapsulation exists simply to prove what code will break
when
you change an object. If you change 'Telephone' then 'ISDNPhone' will
break,
regardless of where it constructs its 'Telephone's.

-- Phlip
======= http://users.deltanet.com/~tegan/home.html =======
Read Bruno the Bandit! at:
http://www.geocities.com/Area51/Zone/5167

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

am...@luckynet.co.il

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <355025EB...@blr.sni.de>#1/1,

"N. Maheswaran" <ma...@blr.sni.de> wrote:
>
> hello,
>
> My name is Maheswaran N. I am working for a company called Siemens
> Information Systems Ltd., Bangalore, India. We develop medical
> application in C++.
>
> I have a problem(taken from Copliens book).
> I have discussed this problem in our company's c++ newsgroup
> and i could not get an answer. So I thought I will post it here
>
> The problem is:
>
> Consider the following piece of code.
>
> /******************** BEGIN **********************/
>
> #include <iostream.h>
>
> class Telephone
> {
> public:
> ~Telephone(){}
>
> protected:
> Telephone(){}
> };
> class ISDNPhone : public Telephone
> {
> public:
> ISDNPhone(){ Telephone t; }
> ~ISDNPhone(){}
> };
> void main()
> {
> ISDNPhone t;
>
> }
>
> /***************** END ************************************/
>
> Here, the base class constructor is protected. And I am trying to
> instantiate a base class object in a derived class constructor.
> The above piece of code is compiling in some compilers and not compiling
>
> in some others. But I dont know why??
>
> I tried compiling the above code in MSVC++4.2, g++(version 2.8.0) and
> CC of Sun Sparc( version 3.0.1 ).
> It did not compile in MSVC++4.2 and g++. But it compiled in
> CC of Sun Sparc.
>
> In our internal newsgroup I got the answer that
> " Since the constructor of the base class is protected, it cannot
> be instantiated anywhere even in a derived class's method."
>
> This argument is quite reasonable. Even I support this. But Coplien
> in his book( page 104 ) says,
> "Actually, the protection against making an object of type Telephone
> is not perfect here: One can be created in member functions of any
> subclass of Telephone, or in any 'friend' functions of class
> Telephone if such should exist".
>
> According to this statement, the above code should compile.
> Now what I want to know is, which is correct out of the above
> two arguments.
>
> In short, should the above code compile or not???
> If not, then is Coplien wrong or is it that I have interpreted wrongly??
>
> If yes, then is it that the Sun Sparc compiler is wrong??
>
> Please reply,
> Thanks in advance,
> Maheswaran N.
>
>
_____________________________________________________________

By defenition th class Telephone isn't abstract class - there
are no abstract member function included. It stand to reason that
the class needs at the very least one public constractor as a must.
However some compilers may overlook this (logical) abomination in
so far as you don't actually try to declare an object (instance) of
the class in question anywhere outside the derived class.

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading

Alan J. Livingston

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

Jawed Karim wrote in message ...

>Your constructor should be public. Always.

Never say Always! (Wasn't that a movie???)

Anyway... There are lots of good reasons for not making a constructor
public. A few reasons are summed up in sections 10.6, 16.19 and 16.22 of
the FAQ.

See:
http://www.cerfnet.com/~mpcline/c++-faq-lite/ctors.html#[10.6]
http://www.cerfnet.com/~mpcline/c++-faq-lite/freestore-mgmt.html#[16.19]
http://www.cerfnet.com/~mpcline/c++-faq-lite/freestore-mgmt.html#[16.22]

As far as the original poster's question, My opinion is, since you've
inherited ISDNTelephone with public access, the code should compile.
However, it doesn't on VC++ 5.0, either. I may be wrong, however. Perhaps
you should repost your question to comp.std.c++

-Alan

==============================================================
Spamguard: Remove the "dot" from between my first and last
name when replying personally to me.

-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d++@ s+:++ a C++(++++)$ ULISC(---)$ P L+>+++ !E W++ N+++>-
o-- K++ w++++>+++++ O---- M-- V PS+++ PE++ Y+ PGP->+ t+@ 5--
X+ R* tv+ b+++ DI++++ D- G e++>+++ h--- r+++ y+++**
------END GEEK CODE BLOCK------
Jawed Karim wrote in message ...

Michael J. Tobler

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <Pine.SOL.3.96.980506...@ux9.cso.uiuc.edu>,
jka...@students.uiuc.edu said...

> Your constructor should be public. Always.
>
> Jawed Karim
>
> jka...@students.uiuc.edu | ja...@planetquake.com
> http://www.ncsa.edu/~jawed/ | http://www.planetquake.com/jawmd2/
>
>
Bzzzzzt! In the implementation of Singletons, this "rule" of your doesnt
apply. Let's see, how would you control/maintain a single printer object
within your application? A really effective way is to use a __private__
constructor:

class Printer
{
public:
friend Printer *makeAPrinter( void ) ;

void sendToPrinter( const char *msg ) ;
virtual ~Printer( ) ;
private:
Printer( ) ;
} ;

Printer *
makeAPrinter( )
{
static Printer *ptr = (Printer *)0 ;

if( ! ptr ) // if we dont have one yet, create it now
{
ptr = new Printer( ) ;
}

return( ptr ) ; // always return the single printer object
}

int main( )
{
Printer *myPrinter = makeAPrinter( ) ;

myPrinter->sendToPrinter( "I'm printing" ) ;

return( 0 ) ;

Michael J. Tobler

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <6iq3eg$8l5$1...@nnrp1.dejanews.com>, am...@luckynet.co.il
said...

[snip]

> By defenition th class Telephone isn't abstract class - there
> are no abstract member function included. It stand to reason that
> the class needs at the very least one public constractor as a must.

Sorry, this is not a true statement, see my reply to "Jawed"

Elf Sternberg

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <355025EB...@blr.sni.de>
"N. Maheswaran" <ma...@blr.sni.de> writes:

>My name is Maheswaran N. I am working for a company called Siemens
>Information Systems Ltd., Bangalore, India. We develop medical
>application in C++.

>I have a problem(taken from Copliens book).
>I have discussed this problem in our company's c++ newsgroup
>and i could not get an answer. So I thought I will post it here

>#include <iostream.h>


>
>class Telephone
>{
> public:
> ~Telephone(){}
>
> protected:
> Telephone(){}
>};
>

>class ISDNPhone : public Telephone // 12


>{
> public:
> ISDNPhone(){ Telephone t; }
> ~ISDNPhone(){}
>};
>
>void main()
>{
> ISDNPhone t;
>
>}


You have made a classic early C++ programmer's mistake, sir.
You have ISDNPhone inheriting from Telephone (an 'is a' relationship--
an ISDNPhone 'is' a Telphone) but your constructor declares a
compositional relationship (a 'has a' relationship-- an ISDNPhone
'has a' telephone as a component).

If you want ISDNPhone to really *be* a telephone (that is, to
inherit all its public and protected methods and members), you have
to say the following in your constructor:

public:
ISDNPhone() : Telephone() { /* Whatever */ }

Base class constructors are invoked *before* derived class
constructors-- if you want to pass them variables, you must specify
how they are passed forward from the derived class constructor in the
manner above. If you call a derived class constructor that doesn't
have a base class constructor invocation, the default constructor for
the base class will be invoked *before* the derived class constructor.
This is covered in AT&T, pg 68, and in Stroustrup (3rd ed.), pg 306.

The reason for your error is then simple-- the Telephone in
your ISDNPhone class exists independantly of ISDNPhone-- it's just a
plain Telephone, and with a protected constructor, it can't be built
as you have it written.

Elf

--
If you bring forth what is within you, Elf M. Sternberg
What you bring forth will save you. www.halcyon.com/elf
If you do not bring forth what is within you,
What you do not bring forth will destroy you. -- Thomas:70

Brahim Djoudi

unread,
May 7, 1998, 3:00:00 AM5/7/98
to N. Maheswaran

Hello.

N. Maheswaran wrote:

> My name is Maheswaran N. I am working for a company called Siemens
> Information Systems Ltd., Bangalore, India. We develop medical
> application in C++.
>
> I have a problem(taken from Copliens book).

( A must read book ! )

> ...
>
> /******************** BEGIN **********************/


>
> #include <iostream.h>
>
> class Telephone
> {
> public:
> ~Telephone(){}
>
> protected:
> Telephone(){}
> };
> class ISDNPhone : public Telephone

> {
> public:
> ISDNPhone(){ Telephone t; }
> ~ISDNPhone(){}
> };
> void main()
> {
> ISDNPhone t;
>
> }
>

> /***************** END ************************************/
>
> Here, the base class constructor is protected. And I am trying to
> instantiate a base class object in a derived class constructor.
> The above piece of code is compiling in some compilers and not compiling
>
> in some others. But I dont know why??
>

> ...


>
> In our internal newsgroup I got the answer that
> " Since the constructor of the base class is protected, it cannot
> be instantiated anywhere even in a derived class's method."

Wrong. A protected constructor may be invoked in any derived class.

> This argument is quite reasonable. Even I support this. But Coplien
> in his book( page 104 ) says,
> "Actually, the protection against making an object of type Telephone
> is not perfect here: One can be created in member functions of any
> subclass of Telephone, or in any 'friend' functions of class
> Telephone if such should exist".

OK. According to old ARM and to new ANSI C++.
In addition, the ISDNPhone default constructor must construct the inherited
part by calling Telephone::Telephone().
Your program is implicitly "coded" by the compiler as following :

#include <iostream.h>

class Telephone
{
public:
~Telephone() {}

protected:
Telephone() {}
};
class ISDNPhone : public Telephone

{
public:
ISDNPhone() : Telephone() // inherited
part must be initialized => a default constructor is required in the base
class
{ Telephone t; }
~ISDNPhone()
{ this->Telephone::~Telephone(); // inherited
part must be deleted (may be protected)
}
};
void main()
// ANSI C++ compilers require int main()
{
ISDNPhone t;

}


Conclusion :
The program must work.

Best regards.


Sai Pulugurtha

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

Derived class objects can access protected members of its
base part, not any arbitrary base class object's protected members,
period.

So,
class ISDNPhone : public Phone {
public:
ISDNPhone() : Phone() // You are initializing the base part of your
// derived class object
{
Phone Phone1; // Here you are trying to create a new instance of
// base class, and hence shouldn't compile
}
};

Hope this helps,
Sai

N. Maheswaran wrote in message <355025EB...@blr.sni.de>...
>hello,


>
>My name is Maheswaran N. I am working for a company called Siemens
>Information Systems Ltd., Bangalore, India. We develop medical
>application in C++.
>
>I have a problem(taken from Copliens book).

Peter Palotas

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

On Wed, 6 May 1998 12:52:23 -0500, mto...@no-spam-ibm.net (Michael J.
Tobler) wrote:
>Printer *
>makeAPrinter( )
>{
> static Printer *ptr = (Printer *)0 ;

// Wouldn't it be more efficient to replace the above statement with
// static Printer *ptr = new Printer();
// And then skip the test below.

>
> if( ! ptr ) // if we dont have one yet, create it now
> {
> ptr = new Printer( ) ;
> }
>
> return( ptr ) ; // always return the single printer object
>}

Peter Palotas <bli...@hem1.passagen.se>

Michael J. Tobler

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

In article <3551dd4...@news.tripnet.se>, bli...@hem1.passagen.se
said...

> On Wed, 6 May 1998 12:52:23 -0500, mto...@no-spam-ibm.net (Michael J.
> Tobler) wrote:
> >Printer *
> >makeAPrinter( )
> >{
> > static Printer *ptr = (Printer *)0 ;
>
> // Wouldn't it be more efficient to replace the above statement with
> // static Printer *ptr = new Printer();
> // And then skip the test below.
[snip]

Yea, I'm just in this crazy habit of checking
for invalid pointers <g>

ed toivanen

unread,
May 12, 1998, 3:00:00 AM5/12/98
to

Not always. I did an assignment once with an overloaded subscript operator,
which required a private constructor.

Cheers, Ed

ed toivanen

unread,
May 12, 1998, 3:00:00 AM5/12/98
to

Make t a pointer, and new it.

class ISDNPhone : public Telephone{
public:

ISDNPhone(){ Telephone * t = new Telephone; }
~ISDNPhone(){}
};

Cheers, Ed


0 new messages