Topic: Why's of C++ -- Part 3 (constructor discussion)


Author: "Greg Brewer" <nospam.gregb@hal-pc.org>
Date: 1999/08/18
Raw View
There is 2 things about C++ constructors I don't understand.

First is why can't constructors be called recursively.  Consider the case
class X {
public:
    const int i1, i2, i3, i4 /*etc*/, i22;
    X(int a1, float a2, float a3, V *);
    // the following is what I would like to do
    X(void) : X(0,0.,10.,NULL) {}
};
I have found ways around this limitation; but, I was wondering if anyone
could explain the rationale behind disallowing it.


The second thing is the implementation of the new static const member
variables.  If you define a class as
class Y {
public:
   static const int maxsize = 64;
   int duplex[maxsize];
   static const float pi = 3.14;
};
then you are required to place a definition in one of your modules for
 const int Y::maxsize;
 const float Y::pi;
and I don't understand why.  In the case of maxsize, it doesn't necessarily
have to exist when compiled for some cpu's.  If maxsize were defined using
enum {maxsize=64}; then it would not have to be defined in a module.  In the
cases were the cpu's instruction set doesn't allow for the value to exist
outsize of a variable state, I would expect that each module could create
its own instance.  In fact, it is my understanding that this was how it was
first done but that it was changed to the current requirement.  One case
were I find this especially bothersome is the case of a template class.  If
you define,
template <class X>
class XX {
public:
   static const float pi = 3.14;
   void Build(X *x) { x->foo(pi);}
};
then this is no way to insure that const float XX<???>::pi is defined for
any usage of XX.

Greg Brewer




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/18
Raw View
In article <7pemfv$7h7$1@news.hal-pc.org>, Greg Brewer
<nospam.gregb@hal-pc.org> writes
>The second thing is the implementation of the new static const member
>variables.  If you define a class as
>class Y {
>public:
>   static const int maxsize = 64;
>   int duplex[maxsize];
>   static const float pi = 3.14;
>};
>then you are required to place a definition in one of your modules for
> const int Y::maxsize;
> const float Y::pi;
>and I don't understand why.

Because, in the context of separate compilation (and even more so with
DLLs) there needs to be a unique point in your code where each variable
is defined.  The relaxation on static const members did not change the
statement from a declaration to a definition, nor should it because a
typical class definition (composed of member declarations) is included
in many compilation units.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/18
Raw View
In article <7pemfv$7h7$1@news.hal-pc.org>, "Greg Brewer"
<nospam.gregb@hal-pc.org> wrote:

> There is 2 things about C++ constructors I don't understand.
>
> First is why can't constructors be called recursively.  Consider the case
> class X {
> public:
>     const int i1, i2, i3, i4 /*etc*/, i22;
>     X(int a1, float a2, float a3, V *);
>     // the following is what I would like to do
>     X(void) : X(0,0.,10.,NULL) {}
> };
> I have found ways around this limitation; but, I was wondering if anyone
> could explain the rationale behind disallowing it.

Complexity? Possible confusion?

I think a forwarding constructor could be useful if it were required that
no other ctor initializers were allowed. But that can be achieved already
with an extra base class:

    class X;

    class X_ {
        // ...
        X_( int i, int j );
        friend class X;
    };

    class X : X_ {
    public:
        X( int i, int j ) : X_( i, j ) { }
        X( int i )        : X_( i, i * 2 ) { }
    };

Convince us that this solution is not adequate.

This solution has the advantage of allowing a differentiation between
common initialization and ctor-specific initialization:

    class X;

    class X_ {
        int common;
        X_( int i, int j ) : common( i * j ) { }
        friend class X;
    };

    class X : X_ {
        int ctor_specific;
    public:
        X( int i, int j ) : X_( i, j ), ctor_specific( i * j ) { }
        X( int i )        : X_( i, i * 2 ), ctor_specific( i ) { }
    };

To understand why we would do this, consider replacing int with a
non-trivial user-defined type that either cannot be assigned to (or is
const), or a type for which copy constructing is much more efficient than
assignment.

I cannot think of any reasonable way to specify this member distinction
with a language-level solution. Any beginnings of ideas lead to chaos.
Don't do it! :-)


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Al Stevens" <alstevens@midifitz.com>
Date: 1999/08/19
Raw View
>The relaxation on static const members did not change the
>statement from a declaration to a definition, nor should it because a
>typical class definition (composed of member declarations) is included
>in many compilation units.

....which includes inline member function declarations that are not defined
elsewhere. I think a static const member declaration could serve as a
definition, too. It's const, so it won't change (the compiler would have to
prohibit casting away constness) and if you prohibit taking its address, it
can be like a true constant literal and look to the compiler just like an
inline member function, something to be compiled inline wherever it is
referenced.

I would have liked to have seen:

class foo {
    const int bar = 123;
    // ...
};

....knowing that I always want that initializer and so that I wouldn't have
to clutter up all the constructors' member initialization lists and ensure
that there could not be differing initializers.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Al Stevens" <alstevens@midifitz.com>
Date: 1999/08/19
Raw View
>class X {
>public:
>    const int i1, i2, i3, i4 /*etc*/, i22;
>    X(int a1, float a2, float a3, V *);
>    // the following is what I would like to do
>    X(void) : X(0,0.,10.,NULL) {}
>};
>I have found ways around this limitation; but, I was wondering if anyone
>could explain the rationale behind disallowing it.

I can guess, although you might not like it. It's probably like the null
declarator you mentioned in another thread: It wasn't disallowed. It was
never allowed. There's a difference.What is permitted in the ctor
initialization list is not a function of all the things that are not
permitted. They allowed what they felt was required.

Necessity being the mother of invention, no one thought to allow that
because no one had a need. Now you can bet that if any of those programmers
on the committee had a real need for such a thing they would have proposed
it. In that case, there would have been deliberation and a vote. If that
happened, which I doubt, someone else can tell you what the arguments were
for both sides.

But it's similar to wanting to do this:

class X {
public:
    X(int);
    X()
    {  X(123); }
};

.... which I thought would be reasonable when I started doing C++ programming
until I understood what the expression X(123); actually does. Both
approaches (what you asked about and what I tried so long ago) are
counter-intuitive to me now probably because the way it works has become
ingrained and I find no problem with it.

You know the workaround. Put the common construction code in a member
function and call that function from all the constructors that need that
construction.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/19
Raw View
In article <N2Gu3.6874$Ce7.122378@newscene.newscene.com>, Al Stevens
<alstevens@midifitz.com> writes
>I would have liked to have seen:
>
>class foo {
>    const int bar = 123;
>    // ...
>};
>
>....knowing that I always want that initializer and so that I wouldn't have
>to clutter up all the constructors' member initialization lists and ensure
>that there could not be differing initializers.

But that would have required extensive extra constraints, including
forbidding the taking of addresses etc. (or other possible smart
solutions).  Now should that restriction only apply when the value is
provided in class, or to all static const members?  If the latter, you
probably break quite a lot of existing code.  If the former, you add to
the cost of maintaining code by replacing an out of class value with an
in class one.

Simply the costs of what was a relatively late change were kept minimal.
That, I think, was the correct decision.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Puduhai Sreeram <psreeram@cas.org>
Date: 1999/08/19
Raw View


Greg Brewer wrote:
> The second thing is the implementation of the new static const member
> variables.  If you define a class as
> class Y {
> public:
>    static const int maxsize = 64;

AFAIK, this is OK to initialize.

>    int duplex[maxsize];
>    static const float pi = 3.14;

Is this allowed? According to Marshall Kline's C++ FAQ only
integral literals are allowed to be initialized in class
body proper if it is a static const. Isn't that so?

Sree


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]