Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > designing classes without default c'tor; using them with STLcontainers and operator>>(istream&)

Reply
Thread Tools

designing classes without default c'tor; using them with STLcontainers and operator>>(istream&)

 
 
Jim Langston
Guest
Posts: n/a
 
      02-02-2008
[rob desbois] wrote:
>> And what exactly would be the problem?

>
> This line is the problem:
> Foo f;
> I cannot and do not want to implement a default constructor for my
> class.


Not
Foo f;
but
Foo f(in);

Something like:

class Foo
{
Foo( istream& in )
{
// read from the stream in and construct the object in this
constructor
}
};

Have a *constructor* accept an input stream itself.

--
Jim Langston
http://www.velocityreviews.com/forums/(E-Mail Removed)


 
Reply With Quote
 
 
 
 
Jerry Coffin
Guest
Posts: n/a
 
      02-03-2008
In article <802ca9df-c78c-4102-9461-2c05526cab88
@d21g2000prf.googlegroups.com>, (E-Mail Removed) says...
> Hi,
>
> I want a class whose invariant is that the contained data members are
> valid - the constructor establishes this invariant, methods assume it
> as their precondition and maintain it as their postcondition.
> This requires the class to NOT have a default constructor.
>
> I need to store instances of this class in STL containers, which
> unfortunately requires that the class has a default constructor.


That is incorrect. When you create a container instance, you can pass it
an object it'll copy as necessary. By default, that's an object created
with the default ctor, but yo can specify an object of your choice if
class doesn't have a default ctor:

struct X {
int y_;
X(int y) : y_(y) {}
};

// the object is the second parameter, so we also have to specify an
// initial size as the first parameter:
std::vector<X> xs(0, X(10));

[ ... ]

> Another requirement is that I need to implement (non-member) I/O
> streaming functions. The output operator<<() is no problem, but again
> with an input operator:
> istream& operator>>(istream& in, const Foo& f);
> I have to use this like so:
> Foo f;
> in >> f;
> This obviously requires, again, that I can construct an instance
> through the default constructor thus generating an invalid object.


This isn't really necessary either. You can construct your temporary
object specifying a parameter to use the non-default ctor, even though
that value is never used otherwise.

Foo f(1); // we'll assume 1 is a valid value:
in >> f;

--
Later,
Jerry.

The universe is a figment of its own imagination.
 
Reply With Quote
 
 
 
 
[rob desbois]
Guest
Posts: n/a
 
      02-04-2008
On Feb 2, 2:13 am, (E-Mail Removed) wrote:
> I won't try to tell you what you should want or should not want. I feel the
> need, however, to point out that picking a non-natural value is not
> necessarily "extremely poor class design". It is what just about any bignum
> class or std::complex does. There is nothing about the number 0 that makes
> it "more natural" than 1. So why should std::complex default construct to
> 0? Well, because it solves problems.


Ok, you're probably right that is isn't 'extremely poor class design',
but the constructor for my actual class looks like this:
MeasurementSettings(const OutputInputMap& inputs, const
InputDivisorMap& divisors, const InputTrafficMap& trafficTypes);
Each of the parameters is a type of std::map.
The class's invariant places requirements on the contents of each of
those maps, and the minimum would be 2 entries in each of them.
Aside from anything else, a default value requires adding 6 entries to
3 different maps which adds noise to the class for no reason other
than to satisfy the requirements of a library class I wish to use.
IMHO the zombie method works a little better for my situation.

> On a related note: many classes do not have a natural comparison.
> Nevertheless it does make sense to at least specialize std::less for those
> classes that support _some_ ordering so that you can use them hassle-free
> in associative containers. Restricting yourself to what feels natural can
> get in the way of solving problems.

My ultimate aim when developing any code to be used by other people is
to aim for the most natural looking solution.
It almost pains me to add support for ordering and default
construction then have to document that they "shouldn't" be used.

--rob
 
Reply With Quote
 
[rob desbois]
Guest
Posts: n/a
 
      02-04-2008
On Feb 2, 4:46 am, "Jim Langston" <(E-Mail Removed)> wrote:
> [rob desbois] wrote:
> >> And what exactly would be the problem?

>
> > This line is the problem:
> > Foo f;
> > I cannot and do not want to implement a default constructor for my
> > class.

>
> Not
> Foo f;
> but
> Foo f(in);


Thanks - sorry that part was in reply to Kai-Uwe on the necessity of
adding a default constructor for std::map<>, not your suggestion of a
constructor taking an istream&.
--rob
 
Reply With Quote
 
[rob desbois]
Guest
Posts: n/a
 
      02-04-2008
On Feb 3, 10:02 am, Jerry Coffin <(E-Mail Removed)> wrote:
> > I need to store instances of this class in STL containers, which
> > unfortunately requires that the class has a default constructor.

>
> That is incorrect. When you create a container instance, you can pass it
> an object it'll copy as necessary. By default, that's an object created
> with the default ctor, but yo can specify an object of your choice if
> class doesn't have a default ctor:


Jerry - that's only relevant for std::vector<> (and perhaps other
sequence containers).
I'm using std::map<> which has no 'sequence construction' and cannot
be given a default object to use.

> > Another requirement is that I need to implement (non-member) I/O
> > streaming functions. The output operator<<() is no problem, but again
> > with an input operator:
> > istream& operator>>(istream& in, const Foo& f);
> > I have to use this like so:
> > Foo f;
> > in >> f;
> > This obviously requires, again, that I can construct an instance
> > through the default constructor thus generating an invalid object.

>
> This isn't really necessary either. You can construct your temporary
> object specifying a parameter to use the non-default ctor, even though
> that value is never used otherwise.
>
> Foo f(1); // we'll assume 1 is a valid value:
> in >> f;


Correct, but again (see my last response to Kai-Uwe) my class's
construction is not as simple as passing an int, but involves
constructing 3 std::map<> instances and adding 2 entries to each. This
is why I want to avoid creating a non-natural default - partially
because I'm not a major fan of it as a general solution, but partially
because in this situation it's 9 lines of code to create that default
value.


Everyone's replies here have been very useful and cleared up in my
mind what is possible, and given me alternative ideas for solutions to
what I thought was a problem.

FYI I opted to create a default constructor for the class which
creates it in a zombie state. Any methods (other than e.g. copy
construct/assign) performed on the zombie will result in an
appropriate exception being thrown. This allows me to use std::map<>
without creating a true default that I don't feel is appropriate to
this situation.
For input streaming I have a constructor taking an istream& as
suggested. I quite like the syntax as it has a 'natural' feel to it
and fits in well with the language.

Thanks all for your time and advice
--rob
 
Reply With Quote
 
[rob desbois]
Guest
Posts: n/a
 
      02-04-2008
On Feb 4, 10:32 am, "[rob desbois]" <(E-Mail Removed)> wrote:
> For input streaming I have a constructor taking an istream& as
> suggested. I quite like the syntax as it has a 'natural' feel to it
> and fits in well with the language.


Actually I tell a complete lie! I followed Alf's advice:
> More generally, think about moving that i/o and possibly serialization
> stuff out of the class proper. Separate concerns. The above is just
> one possibility.


I now have a non-member function to read the constructor parameters
from an istream& and construct the object from that.
Not quite true serialization, but it separates the concerns nicely for
me.

--rob
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Designing lower level classes. Gunter Schelfhout C++ 13 06-30-2008 07:50 AM
how to encapsulate JAI and ImageIO classes into jar file without installing them Java_New Java 1 02-03-2007 07:23 AM
Compacting 5,000 Messages, Moving Them To A Google Account, And Burning Them Onto A CD Martin Computer Support 9 01-14-2007 09:33 PM
Does anyone know them or has any experience with them (good or bad)? Mike Timbell Digital Photography 9 11-13-2003 01:09 AM
Designing presentation layer servlet classes 2BaCook Java 3 11-11-2003 06:47 PM



Advertisments