no default constructor -- bad form?

C

cppaddict

Hi,

I am writing a program and needs to know one of its object members
before it can be initialized. It doesn't really matter for my
question (which a C++ question, not a windows question), but the class
is used in a windows program and has an HWND member ( a handle to a
window), and to make an sense the class must know what the member is.

But this puts me in the position of having no default constructor, and
I've heard that is considered bad form. What is the right way to
handle this situation? Or is it okay to have a class which has no
default constructor?

I found one other thread on this subject in the archives, but I didn't
understand the solution proposed, which involved using the Factory
Design. I don't quite see how this solves the problem, and would love
an explanation of that, if it's relevant. (code is below)

Thanks for any help,
cpp

------BEGIN SNIPPET-----
I have come across many instances where it seems like a class
is most correctly encapsulated when there is NO default constructor.
E.g., I might end up with something like:

class A {
private:
const B& x_;
public:
A(const B& x) : x_(x) {}
// other stuff
};

In this example, I have to initialize x_ to something meaningful when
the class is constructed. More importantly, I want the constructor
to leave A in a valid state, where A is valid only if x_ is meaningfully
initialized (to something only the caller can determine).
How about a factory?

class A {
private:
A() : x_(sX) {};
static B& sX;
public:
static A* makeArrayOfA(const B&x, const long numA) { sX = x; return
new
A[numA];};
....
};

---------END SNIPPET----------
 
L

Leor Zolman

Hi,

I am writing a program and needs to know one of its object members
before it can be initialized. It doesn't really matter for my
question (which a C++ question, not a windows question), but the class
is used in a windows program and has an HWND member ( a handle to a
window), and to make an sense the class must know what the member is.

But this puts me in the position of having no default constructor, and
I've heard that is considered bad form. What is the right way to
handle this situation? Or is it okay to have a class which has no
default constructor?

Someone says it is "bad form" not to have a default constructor? I don't
quite get it. Perhaps in some specific situation, but generally speaking,
classes where it makes no sense for them to be default-initialized are
better off without a default constructor...because of the very reason
you've hit upon: how do you initialize things that /need/ a value if you
don't have a value?

In courses I teach, there are often classes that represent bank accounts of
one type or another, with data members representing account holder's names,
the account number, etc. It wouldn't make a whole lot of sense to allow a
class such as that to be default-initialized.

Some situations where you'll run into trouble, however, are if you need to
create built-in arrays of such objects, or if you use an STL facility that
requires default initialization for the elements involved (for example, if
you use a std::vector, and use resize() to increase the number of elements
in the vector). Otherwise, I wouldn't feel guilty just because a class of
yours doesn't have a default constructor.
-leor
 
J

John Harrison

cppaddict said:
Hi,

I am writing a program and needs to know one of its object members
before it can be initialized. It doesn't really matter for my
question (which a C++ question, not a windows question), but the class
is used in a windows program and has an HWND member ( a handle to a
window), and to make an sense the class must know what the member is.

But this puts me in the position of having no default constructor, and
I've heard that is considered bad form. What is the right way to
handle this situation? Or is it okay to have a class which has no
default constructor?

If you don't have a default constructor then certain code using your class
won't compile, e.g. array declarations. So you should add a default
constructor if it can be done. But if it's really is nonsense to default
constructor then don't do so.
I found one other thread on this subject in the archives, but I didn't
understand the solution proposed, which involved using the Factory
Design. I don't quite see how this solves the problem, and would love
an explanation of that, if it's relevant. (code is below)

Thanks for any help,
cpp

------BEGIN SNIPPET-----
I have come across many instances where it seems like a class
is most correctly encapsulated when there is NO default constructor.
E.g., I might end up with something like:

class A {
private:
const B& x_;
public:
A(const B& x) : x_(x) {}
// other stuff
};

In this example, I have to initialize x_ to something meaningful when
the class is constructed. More importantly, I want the constructor
to leave A in a valid state, where A is valid only if x_ is meaningfully
initialized (to something only the caller can determine).
How about a factory?

class A {
private:
A() : x_(sX) {};
static B& sX;
public:
static A* makeArrayOfA(const B&x, const long numA) { sX = x; return
new
A[numA];};
...
};

The answer describes a way to create an array in the absence of a public
default constructor, which is not what your question was about.

john
 
C

Cy Edmunds

cppaddict said:
Hi,

I am writing a program and needs to know one of its object members
before it can be initialized. It doesn't really matter for my
question (which a C++ question, not a windows question), but the class
is used in a windows program and has an HWND member ( a handle to a
window), and to make an sense the class must know what the member is.

But this puts me in the position of having no default constructor, and
I've heard that is considered bad form. What is the right way to
handle this situation? Or is it okay to have a class which has no
default constructor?

I found one other thread on this subject in the archives, but I didn't
understand the solution proposed, which involved using the Factory
Design. I don't quite see how this solves the problem, and would love
an explanation of that, if it's relevant. (code is below)

Thanks for any help,
cpp

[snip the snippet]

I wouldn't base any aspect of my design on "hearing that such-and-such is
bad form". If you don't want or need a default constructor, don't put one
in.

However, there is some advantage to having a default constructor. For
instance it allows you to put members of your class into a container. Here
are a couple of workarounds.

1) Objects generally have states, and you can define an "uninitialized
state" which would be where your default constructor would leave it. A
method could then be called to complete your object's initialization when
you are ready.

However, this approach has its risks. You would have to consider how to
avoid the mistake of using an unitialized object and also what is going to
happen if you do. If this is more trouble than its worth, leaving out the
default constructor is probably better.

2) Reference counted smart pointers provide copy semantics which allow you
to put them in standard containers no matter what they point to. So:

#include <boost/shared_ptr.hpp>
#include <vector>

typedef PFred boost::shared_ptr<Fred>;
std::vector<PFred> a_vec;

a_vec.push_back(PFred(new Fred(some_argument));
a_vec.back()->fred_function();

<untested (==wrong) code>

If class "Fred" has no default constructor this will work even though
"std::vector<Fred> b_vec;" would not work.
 
H

Howard

However, this approach has its risks. You would have to consider how to
avoid the mistake of using an unitialized object and also what is going to
happen if you do. If this is more trouble than its worth, leaving out the
default constructor is probably better.

But won't leaving out the default constructor open you up to having the
compiler create one for you, in case someone *does* define an array of your
class (or otherwise declare an instance of your object such that the default
constructor would be called)? I think perhaps then it might be better to
make a default construtor, but make it private, wouldn't it?

-Howard
 
J

John Harrison

Howard said:
But won't leaving out the default constructor open you up to having the
compiler create one for you, in case someone *does* define an array of your
class (or otherwise declare an instance of your object such that the default
constructor would be called)? I think perhaps then it might be better to
make a default construtor, but make it private, wouldn't it?

-Howard

The compiler will create a default constructor only for classes which have
no other constructor.

john
 
H

Howard

John Harrison said:
The compiler will create a default constructor only for classes which have
no other constructor.

john

Ok, I see.

My compiler won't let me create an array unless I have a default constructor
(when there are other constructors present), so I know right away that I
either need to write one myself or not create an array like that. Thanks
for the clarification.

-Howard
 
P

Paul

Declare a private default constructor with no implementation (if your
compiler allows that, or an inline {} otherwise.)

This ensures that you have a known default construction, but no one will
ever use it. I often do this with copy constructors and operator= if I don't
want them being used.
 
M

Mark A. Gibbs

Paul said:
Declare a private default constructor with no implementation (if your
compiler allows that, or an inline {} otherwise.)

This ensures that you have a known default construction, but no one will
ever use it. I often do this with copy constructors and operator= if I don't
want them being used.

Just to nitpick here: the latter cases are functionally valid - if you
don't supply the copy constructor and assignment operator, the compiler
will - the former is not - once you supply a non-default constructor,
you don't need to specifically create a dummy default constructor to
avoid it being used.

If you want to make a case for doing it for the sake of clarity, go
ahead. Personally, when i see a (non-pure virtual) declaration, i would
assume there is a definition somewhere (the two cases of the copy
constructor and assignment operator i mentioned above being the only
exceptions) - and i would be right peeved to go hunting all over hell
for it only to find it was a (needless) dummy declaration. On the other
hand, if i see a class declaration with a non-default constructor and no
default constructor, it's a pretty clear statement to me that the class
requires some kind of explicit initialization.

But i do have a question i'm curious about. If i were to write:

class Foo {
public:
Foo(const Foo&) {};
};

is Foo::Foo() generated automatically?

mark
 
A

A. Lloyd Flanagan

Mark A. Gibbs said:
class Foo {
public:
Foo(const Foo&) {};
};

is Foo::Foo() generated automatically?

mark

No. An explicit constructor of any kind disables the automatic
generation of the default constructor.
 
J

Jerry Coffin

(e-mail address removed) (A. Lloyd Flanagan) wrote in message
[ ... ]
No. An explicit constructor of any kind disables the automatic
generation of the default constructor.

Just to clarify something that could be misinterpreted here: in this
case, "explicit constructor" is referring to any constructor that is
not defined automatically. Use of the keyword "explicit" is not
what's at hand.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top