Class objects work like built-in types, but is it worth it?

T

tonytech08

How valuable is it that class objects behave like built-in types? I
appears that the whole "constructor doesn't return a value because
they are called by the compiler" thing is to enable built-in-like
behavior for objects of class type. That leads to the "necessity" for
the exception machinery so that errors from constructors can be
handled. Is all that complexity worth it just to get built-in-like
behavior from class objects? Maybe a better architecture would be for
built-in types and class object types to be accepted as fundamentally
different animals and forego the extensive machinery required to
shoehorn class objects into being something they are not!
 
C

Cupu

How valuable is it that class objects behave like built-in types? I
appears that the whole "constructor doesn't return a value because
they are called by the compiler" thing is to enable built-in-like
behavior for objects of class type. That leads to the "necessity" for
the exception machinery so that errors from constructors can be
handled. Is all that complexity worth it just to get built-in-like
behavior from class objects? Maybe a better architecture would be for
built-in types and class object types to be accepted as fundamentally
different animals and forego the extensive machinery required to
shoehorn class objects into being something they are not!

If I understand your question correctly I'd like to ask what values
would you like to get returned from a constructor?
Obviously since the constructor constructs an object you can receive
either a success or a failure?
Following that logic what happens to the object if the constructor
fails?
The answer to that should be that there is no object ... it couldn't
be constructed thus you have no object which a situation where an
exception looks like exactly the thing you'd want have.
That is, if there's no object force the user to treat that error
(rather than him forgetting to check the return value and segfault
sometime later for no apparent reason).
 
E

Erik Wikström

How valuable is it that class objects behave like built-in types? I
appears that the whole "constructor doesn't return a value because
they are called by the compiler" thing is to enable built-in-like
behavior for objects of class type. That leads to the "necessity" for
the exception machinery so that errors from constructors can be
handled. Is all that complexity worth it just to get built-in-like
behavior from class objects? Maybe a better architecture would be for
built-in types and class object types to be accepted as fundamentally
different animals and forego the extensive machinery required to
shoehorn class objects into being something they are not!

And what would you like "new MyClass()" to return?
 
T

tonytech08

And what would you like "new MyClass()" to return?

OK, 2 responses and both are missing my question so I'll try to
rephrase and clarify. The question is about the value of class objects
behaving like built-in types: How valuable/beneficial/desireable is
that? Or more specifically, was it worth introducing all that
ancillary machinery (exceptions) to get that feature?
 
A

acehreli

The question is about the value of class objects
behaving like built-in types: How valuable/beneficial/desireable is
that? Or more specifically, was it worth introducing all that
ancillary machinery (exceptions) to get that feature?

I am not convinced that exceptions were introduced so that we could
say

MyType m;

I read the Design and Evolution of C++ a long time ago but don't
remember registering anything like that. Perhaps all objects could be
pointers and NULL could be returned?

MyType * m = new MyType();
 
A

acehreli

Fat fingers! :) The post went out incomplete.

I am not convinced that exceptions were introduced so that we could
say

MyType m;

I read the Design and Evolution of C++ a long time ago but don't
remember registering anything like that. Perhaps all objects could be
pointers and NULL could be returned?

MyType * m = new MyType();

[I was going to add...]

Then we would have to check every object creation:

if (!m) // cannot continue

We wouldn't be able to chain function calls:

calculate(make_first(), make_second());

It should be done noisily:

FirstType * f = make_first();
if (!f) goto bail;

SecondType * s = make_second();
if (!s) goto bail;

calculate(f, s);

That would be C-like in a bad way. :)

Can you think of a better way without exceptions from constructors?

Ali
 
E

Erik Wikström

OK, 2 responses and both are missing my question so I'll try to
rephrase and clarify. The question is about the value of class objects
behaving like built-in types: How valuable/beneficial/desireable is
that? Or more specifically, was it worth introducing all that
ancillary machinery (exceptions) to get that feature?

Yes, it is desirable to have objects look like built-in types. But you
do not have to have exceptions to do this, you could instead requiring a
failing constructor to construct the object into a failed state which
can be checked after construction:

MyObject obj;
if (obj.invalid())
{
// Handle situation
}

The reason for exceptions is that they allow for a much better and
simpler error handling than to old way of return-codes. In fact even
languages which does not have object might have exceptions (such as ML,
a functional language).
 
P

peter koch

OK, 2 responses and both are missing my question so I'll try to
rephrase and clarify. The question is about the value of class objects
behaving like built-in types: How valuable/beneficial/desireable is
that? Or more specifically, was it worth introducing all that
ancillary machinery (exceptions) to get that feature?

What makes you believe that exceptions are useful only for catching
errors in constructors? On the contrary, exceptions are a general and
useful error-handling mechanism.
As for your original question, classes behaving like ordinary built-in
types are quite useful. Imagine not being able to have all the many
useful types available that naturally are perceived as value-types:
std::string, complex and the many containers such as std::vector.

/Peter
 
T

tonytech08

I am not convinced that exceptions were introduced so that we could
say

  MyType m;

I read the Design and Evolution of C++ a long time ago but don't
remember registering anything like that.
"Behaving like built-in type" means much more than "MyType m;"
example. Think about the following group of special "things" in a
class implemented to behave like a built-in type: default constructor,
copy constructor, assignment operator, destructor. Think about what
happens when you pass an object by value as a function argument.
Somehow, you have to handle potential errors from the copy
constructor. Solution: exceptions.

So more machinery than just exception to get built-in-type behavior:
default constructor, copy constructor, assignment operator,
destructor, compiler machinery to call these member functions. Is it
built-in-type behavior that lucrative to be worth all that?
Perhaps all objects could be
pointers and NULL could be returned?

MyType * m = new MyType();

(Aside/separate topic: That would be Simula then, right? That would
bring up the question of whether class objects can be of local (stack)
objects (which performance and convenience decidedly agree they should
be able to be)).
 
A

acehreli

"Behaving like built-in type" means much more than "MyType m;"
example. Think about the following group of special "things" in a
class implemented to behave like a built-in type: default constructor,
copy constructor, assignment operator, destructor.

Because of some of those, classes are better than built-in types.
That's part of the reasons why built-in types are referred to as
"second class" types:

- default constructor: missing for built-in types

- assignment operator: not always what we want for built-in types

- destructor: empty for built-in types; not always what we want
Think about what
happens when you pass an object by value as a function argument.
Somehow, you have to handle potential errors from the copy
constructor. Solution: exceptions.

Yes, exceptions are a mechanism of handling errors. The alternative of
handing error codes from layer to layer is not better.

They are not for built-in type behavior.
So more machinery than just exception to get built-in-type behavior:
default constructor, copy constructor, assignment operator,
destructor, compiler machinery to call these member functions. Is it
built-in-type behavior that lucrative to be worth all that?

They are all very important features without any connection to trying
to be like built-in types. Those are basic operations on types that we
need. The reason that built-in types have those operations is because
they are fundamental operations.

If those features are not important enough, one could always use C for
a while and come back to C++. ;)

Ali
 
P

peter koch

"Behaving like built-in type" means much more than "MyType m;"
example. Think about the following group of special "things" in a
class implemented to behave like a built-in type: default constructor,
copy constructor, assignment operator, destructor. Think about what
happens when you pass an object by value as a function argument.
Somehow, you have to handle potential errors from the copy
constructor. Solution: exceptions.

So more machinery than just exception to get built-in-type behavior:
default constructor, copy constructor, assignment operator,
destructor, compiler machinery to call these member functions. Is it
built-in-type behavior that lucrative to be worth all that?

These features are there to enable you to write solid code. Without
these, there is no easy way to write readable, robust code. For one
thing, the assignment operators and constructors ensure that your
objects remain consistent.
Also note that none of these are really needed: you could remove e.g.
the assignment operator and exceptions and still write something that
would look like C++ code, but the prize you pay is the burden you put
on all users of your classes. They would e.g. have to remember that
objects of your class should not be assigned to but should use a
special assignment function call, and they would have to be aware that
a constructed object might not have a valid state and might be
unusable and so on. It is a very high prize to pay for nothing but
some saved time for the compiler developers.They could. But why would you want to impose such a large overhead on
us poor programmers?

/Peter
 
J

Juha Nieminen

tonytech08 said:
How valuable is it that class objects behave like built-in types?

Without that behavior you couldn't create, for example, generic data
containers which work with both built-in types and user-defined classes.
But since user-defined classes can be made to behave like built-in
types, that simplifies generic programming a great deal.

Without this feature there would be only two possible choices:

1) Generic containers cannot support built-in types, only user-defined
classes. This would not only seriously cripple the usefulness of such
containers, it would be a major setback in efficiency when you want to
use the container for built-in types. (Basically you would have to write
wrappers for all built-in types, with all of their drawbacks. AFAIK this
is the case in Java.)

2) Make built-in types work like classes. This means that all objects
are allocated dynamically and are dynamically bound (like they are in
some languages). While in some cases this would be a useful thing (which
is the reason why those some languages do it in the first place), this
would seriously hinder the efficiency of built-in types.
(And no, the compiler would not be able to optimize dynamic binding
etc. out of the built-in types in C++ because, among other things, it
must support precompiled and dynamically loadable libraries.)

Another somewhat related benefit is that it makes it easier to
abstract your code. For example:

typedef int MyIntegral;

If you use that type consistently for a specific role in your code,
and later you need to change it to something else, you can change just
that line and that's it. No need to change anything else.
If the type you need to change it to is too complex to be a built-in
type, you can replace it with a class, no problem.
 
T

tonytech08

(Aside/separate topic: That would be Simula then, right? That would
bring up the question of whether class objects can be of local (stack)
objects (which performance and convenience decidedly agree they should
be able to be)).

Which is, of course, info direct from D&E.
 
T

tonytech08

Fat fingers! :) The post went out incomplete.

I am not convinced that exceptions were introduced so that we could
say
  MyType m;
I read the Design and Evolution of C++ a long time ago but don't
remember registering anything like that. Perhaps all objects could be
pointers and NULL could be returned?
  MyType * m = new MyType();

[I was going to add...]

Then we would have to check every object creation:

if (!m) // cannot continue

We wouldn't be able to chain function calls:

  calculate(make_first(), make_second());

It should be done noisily:

  FirstType * f = make_first();
  if (!f) goto bail;

  SecondType * s = make_second();
  if (!s) goto bail;

  calculate(f, s);

That would be C-like in a bad way. :)

Can you think of a better way without exceptions from constructors?

Ali- Hide quoted text -

- Show quoted text -

Surely you are not suggesting that constructors lack return values
other than because of the "ctors enable class objects to behave like
built-in types", are you? Because, I think, that is default
constructors main purpose (i.e., the reason they were implemented as
part of the language).
 
T

tonytech08

Yes, it is desirable to have objects look like built-in types. But you
do not have to have exceptions to do this, you could instead requiring a
failing constructor to construct the object into a failed state which
can be checked after construction:

  MyObject obj;
  if (obj.invalid())
  {
    // Handle situation
  }

That's the simple case though. I'm sure the gurus here will be able to
come up with object temporary creation/lifetime where you as a
developer would not have even the opportunity to do such checking.
(And no, I'm not arguing the opposite of what I asked originally).
The reason for exceptions is that they allow for a much better and
simpler error handling than to old way of return-codes. In fact even
languages which does not have object might have exceptions (such as ML,
a functional language).

Apparently though, it's not a should we/shouldn't we implement
exceptions in the language, it's they HAD to (which brings the obvious
question if that is the main reason. I do think it is the main reason,
for many developers don't use exceptions unless they have to, such as
in constructors, operators etc). Not to be argumentative though, I'm
trying to decide whether class objects behaving like built in types is
worth all the complexity that brings. Perhaps only certain (a very
small subset) classes should be coded as "orthodox canonical
form" (Coplien) classes that may need exceptions.
 
T

tonytech08

What makes you believe that exceptions are useful only for catching
errors in constructors?

That I said that exceptions are a solution to the obvious problem of
handling errors in constructors (and operators, etc.), does not imply
how I feel about their use elsewhere. And discussion of exceptions is
pretty much off topic from the original question.
As for your original question, classes behaving like ordinary built-in
types are quite useful. Imagine not being able to have all the many
useful types available that naturally are perceived as value-types:
std::string, complex and the many containers such as std::vector.

You could still have those though without coding them up to behave
like built-ins. And maybe they should be coded up that way. Maybe
those 2 examples make for good "built-in behavin'" class objects. But
maybe there is a line to be drawn as to where that pattern/paradigm is
used. It's not necessarily true that just because the machinery is
there for special purpose that the machinery should be used everywhere
and all of the time. (Though, which may be obvious, I'm pondering if
it would be painful or just a tad less convenient to use it nowhere
and never and thereby shrinking the implementation of the language way
down).
 
T

tonytech08

tonytech08 said:
How valuable is it that class objects behave like built-in types? [...]

  How valuable do you consider 'std::string'? 'std::eek:fstream?
  'std::complex'? All those container types? Function objects?
  Iterators? Thread classes? Automatic locks? ...?

  Schobi

Is it annoying when someone answers every response here? Is it rude
not to?

Anyway, the question isn't whether OO is good/bad. It's whether making
class objects behave like built-in types is overkill.
 
T

tonytech08

Because of some of those, classes are better than built-in types.
That's part of the reasons why built-in types are referred to as
"second class" types:

- default constructor: missing for built-in types

- assignment operator: not always what we want for built-in types

- destructor: empty for built-in types; not always what we want


Yes, exceptions are a mechanism of handling errors. The alternative of
handing error codes from layer to layer is not better.

They are not for built-in type behavior.

I'm going to ignore the tangent topic of exceptions for now.
They are all very important features without any connection to trying
to be like built-in types. Those are basic operations on types that we
need. The reason that built-in types have those operations is because
they are fundamental operations.

You could be right, but I'm not sure what you are trying to say. I
suggested that the set of class functions known as default
constructor, copy constructor, assignment operator and destructor are
a direct result of the goal to enable class objects to behave like
built-in types. Further, that those are not even enough: then you have
to figure out a way to handle errors from those kinds of things, and
that leads directly to why exception handling is used in those.
If those features are not important enough, one could always use C for
a while and come back to C++. ;)

Or as few C++ COMPLEX features as possible unless it "hurts to bad"
not to while still using C++ features that are a bit more elegant?
 
T

tonytech08

These features are there to enable you to write solid code.

It would be interesting to hear the designer expound about the
importance and value of giving class objects the capability to behave
like built-ins, and weighing that against the implementation "costs".
I think I'm convinced that class objects should be allowed to be stack
objects, but I'm no so sure that having class objects behave like
built-ins is that worthwhile. I use the machinery too, but that's
because I learned it that way. Maybe it's just not all that necessary
and I don't know just because I haven't tried to build stuff without
it (maybe to answer my own question I'll have to build something,
avoid the heavy-lifting C++ features, come up with some new ways of
doing stuff and sit back and evaluate it afterwards). I was thinking
though that with all the experience in these rooms, someones have
already "been there, done that". But but by "been there, done that", I
don't mean "have C coding background", that's where I started too. I
mean someone who has used C++ for quite a few years and then
reassessed and tried other ways to "skin the cat".
Without
these, there is no easy way to write readable, robust code.

(I'll let everyone jump on you for that statement).
For one
thing, the assignment operators and constructors ensure that your
objects remain consistent.
Also note that none of these are really needed: you could remove e.g.
the assignment operator and exceptions and still write something that
would look like C++ code, but the prize you pay is the burden you put
on all users of your classes. They would e.g. have to remember that
objects of your class should not be assigned to but should use a
special assignment function call, and they would have to be aware that
a constructed object might not have a valid state and might be
unusable and so on. It is a very high prize to pay for nothing but
some saved time for the compiler developers.

At least that would be the "inside the box" perspective. ;)
 
T

tonytech08

  Without that behavior you couldn't create, for example, generic data
containers which work with both built-in types and user-defined classes.

That of course is not correct.
But since user-defined classes can be made to behave like built-in
types, that simplifies generic programming a great deal.

Maybe, if you adhere to one specific way of designing containers (?).
  Without this feature there would be only two possible choices:

1) Generic containers cannot support built-in types, only user-defined
classes.

The way STL containers are designed is not the only possibility. You
seem to be fixated on STL container designs/architecture. (?)
2) Make built-in types work like classes. This means that all objects
are allocated dynamically

That may not be a bad idea though if you say "container objects are
allocated from the heap" rather than as you said it which seems to
imply that ALL object everywhere and all the time must be heap
allocated.
and are dynamically bound

I don't know what that means or what you mean by it.
(like they are in
some languages). While in some cases this would be a useful thing (which
is the reason why those some languages do it in the first place), this
would seriously hinder the efficiency of built-in types.

It wouldn't change built-in efficiency in the least or in any way. Did
you mean using those things from containers? Perhaps you are thinking
built-in arrays and not containers at all?
  (And no, the compiler would not be able to optimize dynamic binding
etc. out of the built-in types in C++ because, among other things, it
must support precompiled and dynamically loadable libraries.)

Whoa, I think you are overscoping the the original topic by a mile by
bringing in dynamic binding and loadable libraries!
 

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,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top