C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

hiding default constructors with private or protected -- que

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
csharpuser
Guest





PostPosted: Sat Jun 11, 2005 10:38 am    Post subject: hiding default constructors with private or protected -- que Reply with quote



Questions about making default constructor protected so as to hide it.

Hi,

I have the following class where I make the default constructor private
(I also played with protected).

class Movie
{
public:
Movie( const std::string& title);
virtual ~Movie(void);
std::string getTitle() const {return _title;}

protected:
std::string _title; // title of movie
private:
Movie(); // no default constructors allowed....


I made the default constructor private because I did not want someone
to instatiate the class with no title.
In particular, I did not want someone coming along a writing the
following class:

class RentalMovie :
public Movie
{
public:


RentalMovie( const std::string& title, int pricecode =
PriceCodes::REGULAR); // constructor
RentalMovie(const RentalMovie &); // copy constructor
RentalMovie & operator=(const RentalMovie &); // assignmnet operator
virtual ~RentalMovie(void);

protected:
RentalMovie();// {} // disallow default construction
private:

};

// Movie.cpp file
RentalMovie::RentalMovie( const std::string& title, int PriceCode ) :
Movie(title)
{
pPrice = 0;
setPriceCode(PriceCode);
}

Notice the constructor calls the Movie constructor filling in the
title. However, if I accidentally write
the following:

// Movie.cpp file
RentalMovie::RentalMovie( const std::string& title, int PriceCode )
{
pPrice = 0;
setPriceCode(PriceCode);
}

it still compiles and runs! And it ends up calling the Movie classes
default constructor, even though it's
private. This is exactly the behavior I was trying to guard against.
That is a client programmer accidentally
forgetting to fill in the ": Movie(title)".

Can someone tell me if this is the behavior I should expect. That is,
is this the standard? I am using
Visual Studio 7.0. Is there a better way to enforce the desired
behavior that I want for Movie class?

If you've made it this far, I have another related problem. After
writing the classes Movie and RentalMovie,
I wrote the class Rental like so:


#include "RentalMovie.h"
class Rental {
public:
Rental( const RentalMovie& movie, int daysRented );

private:
RentalMovie _movie;

};

inline Rental::
Rental( const RentalMovie& movie, int daysRented )
: _movie( movie )
, _daysRented( daysRented ) {}


I was a little surprised that this compiled. After all, I made the
default constructor for RentalMovie
protected, but you clearly see the line:
RentalMovie _movie

Admittedly, _movie is filled in by the constructor for Rental with a
valid RentalMovie object that was
constructed elsewhere. Does the compiler somehow "know" to allow a
default constructor in this case? Does
it reason, "ah well, he's about to use copy constructor anyhow". Are
there some rules written down on this?

References/advice/flames on either or both of the above two questions
would be much appreciated.

Thanks,

David


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Daughtry
Guest





PostPosted: Sat Jun 11, 2005 6:30 pm    Post subject: Re: hiding default constructors with private or protected -- Reply with quote



If you make the default constructor protected then derived classes and
friends can call it. If you make it private then only that class and
friends can call it. If your compiler allows anything else then it's
broken.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Sat Jun 11, 2005 6:30 pm    Post subject: Re: hiding default constructors with private or protected -- Reply with quote



On Sat, 11 Jun 2005 14:38:09 +0400, csharpuser <csharpuser (AT) hotmail (DOT) com>
wrote:

Quote:
Questions about making default constructor protected so as to hide it.

Hi,

I have the following class where I make the default constructor private
(I also played with protected).

class Movie
{
public:
Movie( const std::string& title);
virtual ~Movie(void);
std::string getTitle() const {return _title;}

protected:
std::string _title; // title of movie
private:
Movie(); // no default constructors allowed....


I made the default constructor private because I did not want someone
to instatiate the class with no title.

You don't have to declare a private default constructor here. As you
declared a constructor which takes an argument, it prevents a compiler
from generating a default one.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
alerma
Guest





PostPosted: Sat Jun 11, 2005 7:41 pm    Post subject: Re: hiding default constructors with private or protected -- Reply with quote

something is wrong here. consider the following simplified example:

#include <iostream>
using namespace std;

class A
{
int m_a;
protected:
A() {}

public:
A(int a):m_a(a) {}
};

class B : public A
{
int m_b;
B() {}

public:
B(int b):A(b), m_b(b) {}
};

int main()
{
B b(5);
}

you have to decalre A() constructor as protected, otherwise the code
won't compile. From this point if you omit a call to A(b) from B init
list it calls the default ctor implicitly.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Conrad Z.
Guest





PostPosted: Mon Jun 13, 2005 7:59 am    Post subject: Re: hiding default constructors with private or protected -- Reply with quote


"csharpuser" <csharpuser (AT) hotmail (DOT) com> schreef in bericht
news:1118424842.552362.206210 (AT) f14g2000cwb (DOT) googlegroups.com...
Quote:
Questions about making default constructor protected so as to hide it.

Hi,

I have the following class where I make the default constructor private
(I also played with protected).

class Movie
{
public:
Movie( const std::string& title);
virtual ~Movie(void);
std::string getTitle() const {return _title;}

protected:
std::string _title; // title of movie
private:
Movie(); // no default constructors allowed....


I made the default constructor private because I did not want someone
to instatiate the class with no title.
In particular, I did not want someone coming along a writing the
following class:

class RentalMovie :
public Movie
{
public:


RentalMovie( const std::string& title, int pricecode =
PriceCodes::REGULAR); // constructor
RentalMovie(const RentalMovie &); // copy constructor
RentalMovie & operator=(const RentalMovie &); // assignmnet
operator
virtual ~RentalMovie(void);

protected:
RentalMovie();// {} // disallow default construction
private:

};

// Movie.cpp file
RentalMovie::RentalMovie( const std::string& title, int PriceCode ) :
Movie(title)
{
pPrice = 0;
setPriceCode(PriceCode);
}

Notice the constructor calls the Movie constructor filling in the
title. However, if I accidentally write
the following:

// Movie.cpp file
RentalMovie::RentalMovie( const std::string& title, int PriceCode )
{
pPrice = 0;
setPriceCode(PriceCode);
}

it still compiles and runs! And it ends up calling the Movie classes
default constructor, even though it's
private. This is exactly the behavior I was trying to guard against.
That is a client programmer accidentally
forgetting to fill in the ": Movie(title)".

Can someone tell me if this is the behavior I should expect. That is,
is this the standard? I am using
Visual Studio 7.0. Is there a better way to enforce the desired
behavior that I want for Movie class?


I have tried your code with BorlandC++ Builder5 and it works as you
expected: it
compiles with the RentalMovie contructor that correctly calls the
Movie(string)
constructor and fails to compile whith the implicit call of the default
constructor.
One possible reason for your compiler to do what it does is because it
converts
the call to the default contructor, which is prohibited, to a call to the
Movie(string) constructor with an empty string.
You may try to make this constructor explicit!

class Movie
{
public:
explicit Movie( const std::string& title);

Antoon



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Mon Jun 13, 2005 9:12 am    Post subject: Re: hiding default constructors with private or protected -- Reply with quote

csharpuser wrote:

Quote:
I have the following class where I make the default
constructor private (I also played with protected).

class Movie
{
public:
Movie( const std::string& title);
virtual ~Movie(void);
std::string getTitle() const {return _title;}

protected:
std::string _title; // title of movie
private:
Movie(); // no default constructors allowed....

Except from within Movie itself.

Quote:
I made the default constructor private because I did not want
someone to instatiate the class with no title.

Unless you want to use the default constructor within Movie
itself, the simplest solution is not to provide it at all. The
compiler will only provide a default default constructor if you
have declared no constructors. (Note that this is not the case
for the copy constructor; the compiler provides a copy
constructor even if you've defined other constructors.)

Quote:
In particular, I did not want someone coming along a writing
the following class:

class RentalMovie :
public Movie
{
public:
RentalMovie( const std::string& title, int pricecode =
PriceCodes::REGULAR); // constructor
RentalMovie(const RentalMovie &); // copy constructor
RentalMovie & operator=(const RentalMovie &); // assignmnet operator
virtual ~RentalMovie(void);

protected:
RentalMovie();// {} // disallow default construction
private:

};

// Movie.cpp file
RentalMovie::RentalMovie( const std::string& title, int PriceCode ) :
Movie(title)
{
pPrice = 0;
setPriceCode(PriceCode);
}

Notice the constructor calls the Movie constructor filling in
the title. However, if I accidentally write the following:

// Movie.cpp file
RentalMovie::RentalMovie( const std::string& title, int PriceCode )
{
pPrice = 0;
setPriceCode(PriceCode);
}

it still compiles and runs! And it ends up calling the Movie
classes default constructor, even though it's private.

If Movie::Movie() is private, the above should not compile. If
you have not declared a default constructor, it shouldn't
compile either.

Quote:
This is exactly the behavior I was trying to guard against.

Either you accidentally missed something (and the default
constructor was either public or protected), or the compiler has
a serious bug.

Quote:
That is a client programmer accidentally forgetting to fill in
the ": Movie(title)".

Can someone tell me if this is the behavior I should expect.
That is, is this the standard? I am using Visual Studio 7.0.
Is there a better way to enforce the desired behavior that I
want for Movie class?

The simplest solution is simply not to declare a default
constructor at all. Otherwise, a private constructor should not
be callable from a derived class.

Quote:
If you've made it this far, I have another related problem.
After writing the classes Movie and RentalMovie, I wrote the
class Rental like so:

#include "RentalMovie.h"
class Rental {
public:
Rental( const RentalMovie& movie, int daysRented );

private:
RentalMovie _movie;

};

inline Rental::
Rental( const RentalMovie& movie, int daysRented )
: _movie( movie )
, _daysRented( daysRented ) {}

I was a little surprised that this compiled. After all, I
made the default constructor for RentalMovie protected, but
you clearly see the line:

RentalMovie _movie

But this line only declares the member variable. It doesn't
instantiate it, and so doesn't require a constructor.

The constructor for _movie is called from the constructor of
Rental. At that point, if there is no default constructor, or
the default constructor is not accessible, you must initialize
_movie explicitly, or the compiler should complain.

Quote:
Admittedly, _movie is filled in by the constructor for Rental
with a valid RentalMovie object that was constructed
elsewhere. Does the compiler somehow "know" to allow a
default constructor in this case?

It doesn't allow the default constructor. The default
constructor is never called.

Quote:
Does it reason, "ah well, he's about to use copy constructor
anyhow". Are there some rules written down on this?

There is an ISO standard for the language, which specifies the
rules in excrutiating detail. In this case, the general rule is
fairly simple: the constructor of Rental calls the constructors
of each of the sub-objects in the order they are declared in the
class. If there is an initializer specified, it uses the
constructor implied by the initializer. If not, the compiler
uses the default constructor. If the constructor it wants to
use doesn't exist, or is not accessible, it is an error.

If the constructor has been declared, but not implemented, the
behavior is formally undefined; in practice, you will get an
error from the linker. In all other cases, the standard
requires an error message from the compiler.

Note too that when deciding which constructor it wants to call,
the compiler uses overload resolution; if some of the
constructors are member templates, it may also try to
instantiate them. This can, occasionally, lead to surprising
results.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.