When a default constructor necessary?

Discussion in 'C++' started by highli, Jul 24, 2004.

  1. highli

    highli Guest

    When a non-default constructor provided in a class, the default constructor
    is not available anymore.

    In what cases shall a default constructor be defined explicitly?

    Specifically, in the following cases, shall a default constructor be
    provided?


    1. Inheritance. Class A is derived from class B. Shall a default constructor
    be defined for A and B?

    2. Virtual inheritance.

    3. When class A contains class B, Shall a default constructor be defined for
    A and B?

    4. Abstract base class.

    Thanks in advance!
     
    highli, Jul 24, 2004
    #1
    1. Advertising

  2. * highli:
    >
    > in the following cases, shall a default constructor be provided?
    >
    > 1. Inheritance. Class A is derived from class B. Shall a default constructor
    > be defined for A and B?
    >
    > 2. Virtual inheritance.
    >
    > 3. When class A contains class B, Shall a default constructor be defined for
    > A and B?
    >
    > 4. Abstract base class.


    Those possible reasons are _unrelated_ to whether a default constructor
    should be defined.

    Define a default constructor when there is natural default state.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 24, 2004
    #2
    1. Advertising

  3. highli

    SaltPeter Guest

    "highli" <> wrote in message
    news:lDBMc.132074$...
    > When a non-default constructor provided in a class, the default

    constructor
    > is not available anymore.
    >
    > In what cases shall a default constructor be defined explicitly?
    >
    > Specifically, in the following cases, shall a default constructor be
    > provided?
    >
    >
    > 1. Inheritance. Class A is derived from class B. Shall a default

    constructor
    > be defined for A and B?
    >
    > 2. Virtual inheritance.
    >
    > 3. When class A contains class B, Shall a default constructor be defined

    for
    > A and B?
    >
    > 4. Abstract base class.
    >
    > Thanks in advance!
    >


    None of these absolutely require a default constructor assuming that you
    have defined what a default constructor is. You can provide an alternate
    constructor to satisfy all the above mentioned conditions just like you
    might mix default constructors and alternate cstors to generate the end
    product.

    Whats important is that your derived class indicate which cstor is
    appropriate to create base/members in its cstor's initialization list. Which
    is critical since the base class(es) and member class(es) need to be
    generated before the cstor of the derived class is invoked. You can't build
    the house if you haven't poured the foundation.

    If what you are asking is whether defining cstors are a requirement, the
    answer is no, but since C++ gives the power to define creation, why not take
    charge and control the process since that may help in the case of
    tracing/debugging? Not to mention the fact that you only get what you want
    with explicit invocations.

    Incidentally, what you might want to spend more time on, is whether and what
    copy cstor, as well as assignment operator you might need. Look up the
    subject of "deep copy".
     
    SaltPeter, Jul 25, 2004
    #3
  4. On Sat, 24 Jul 2004 22:44:33 GMT, highli <> wrote:

    > When a non-default constructor provided in a class, the default
    > constructor
    > is not available anymore.
    >
    > In what cases shall a default constructor be defined explicitly?
    >


    When you want the default constructor to do something different from the
    compiler generated default constructor or when you want a default
    constructor and the compiler won't generate one for you for some reason.

    > Specifically, in the following cases, shall a default constructor be
    > provided?
    >
    >
    > 1. Inheritance. Class A is derived from class B. Shall a default
    > constructor
    > be defined for A and B?
    >
    > 2. Virtual inheritance.
    >
    > 3. When class A contains class B, Shall a default constructor be defined
    > for
    > A and B?
    >
    > 4. Abstract base class.
    >


    None of these issues are relevant in any way that I can see.

    john
     
    John Harrison, Jul 25, 2004
    #4
  5. highli

    Sharad Kala Guest

    "highli" <> wrote in message
    news:lDBMc.132074$...
    > When a non-default constructor provided in a class, the default

    constructor
    > is not available anymore.
    >
    > In what cases shall a default constructor be defined explicitly?


    When you want to create an array of objects of your class. You can't do so
    in the absence of a default constructor. Another reason to switch over to
    std::vector which doesn't impose such a restriction.

    -Sharad
     
    Sharad Kala, Jul 25, 2004
    #5
  6. * Sharad Kala:
    >
    > "highli" <> wrote in message
    > news:lDBMc.132074$...
    > > When a non-default constructor provided in a class, the default

    > constructor
    > > is not available anymore.
    > >
    > > In what cases shall a default constructor be defined explicitly?

    >
    > When you want to create an array of objects of your class.


    That's most often a Very Bad reason, because it most often adds an
    unusable state. Use smart-pointers instead. E.g. boost::shared_ptr.


    > You can't do so in the absence of a default constructor.


    I'm sure that "highli" can write e.g.

    class Point
    {
    int myX, mY;
    public:
    Point( int x, u ): myX( x ), myY( y ) {}
    int x() const { return x; }
    int y() const { return y; }
    };

    Point const points[] =
    { Point( 1, 2 ), Point( 3, 4 ), Point( 5, 6 ) };

    or some such, without thinking twice (or at least he or she will be able
    to do this after a while).


    > Another reason to switch over to
    > std::vector which doesn't impose such a restriction.


    It's not very clear what you mean here.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #6
  7. highli

    Sharad Kala Guest

    "Alf P. Steinbach" <> wrote in message
    news:...
    > * Sharad Kala:
    > >
    > > "highli" <> wrote in message
    > > news:lDBMc.132074$...
    > > > When a non-default constructor provided in a class, the default

    > > constructor
    > > > is not available anymore.
    > > >
    > > > In what cases shall a default constructor be defined explicitly?

    > >
    > > When you want to create an array of objects of your class.

    >
    > That's most often a Very Bad reason, because it most often adds an
    > unusable state. Use smart-pointers instead. E.g. boost::shared_ptr.


    I was just mentioning one case when things can not be done without a default
    constructor since it was not mentioned in any of the other replies. Not
    recommending any way to do things.

    > > You can't do so in the absence of a default constructor.

    >

    [snip]
    > > Another reason to switch over to
    > > std::vector which doesn't impose such a restriction.

    >
    > It's not very clear what you mean here.



    Read the FAQ - http://www.parashift.com/c -faq-lite/ctors.html#faq-10.5

    -Sharad
     
    Sharad Kala, Jul 25, 2004
    #7
  8. * Sharad Kala:
    >
    > "Alf P. Steinbach" <> wrote in message
    > news:...
    > > * Sharad Kala:
    > > >
    > > > "highli" <> wrote in message
    > > > news:lDBMc.132074$...
    > > > > When a non-default constructor provided in a class, the default
    > > > constructor
    > > > > is not available anymore.
    > > > >
    > > > > In what cases shall a default constructor be defined explicitly?
    > > >
    > > > When you want to create an array of objects of your class.

    > >
    > > That's most often a Very Bad reason, because it most often adds an
    > > unusable state. Use smart-pointers instead. E.g. boost::shared_ptr.

    >
    > I was just mentioning one case when things can not be done without a default
    > constructor since it was not mentioned in any of the other replies. Not
    > recommending any way to do things.
    >
    > > > You can't do so in the absence of a default constructor.

    > >

    > [snip]
    > > > Another reason to switch over to
    > > > std::vector which doesn't impose such a restriction.

    > >
    > > It's not very clear what you mean here.

    >
    > Read the FAQ - http://www.parashift.com/c -faq-lite/ctors.html#faq-10.5


    Thank you.

    I'm CC'ing this to Marshall Cline; this FAQ item wasn't meant to create
    the impression you got (note that at the very start it mentions "except
    as discussed below"). In short, the correct version is that you can't
    create an array of objects of a class type that has no default
    constructor unless (a) an array initializer is given (the FAQ item gives
    an example of that at the end, essentially the same example that I gave
    and you snipped but without the typos... ;-) ), or (b) placement new is
    used, as it is internally in std::vector. Point (b) should perhaps be
    mentioned directly in this FAQ item, and both points placed at the top.

    Now study the example at the _end_ of that FAQ item... ;-)

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #8
  9. highli

    Sharad Kala Guest

    "Alf P. Steinbach" <> wrote in message
    news:...
    > * Sharad Kala:
    > >

    [snip]
    > > Read the FAQ -

    http://www.parashift.com/c -faq-lite/ctors.html#faq-10.5
    >
    > Thank you.


    Most welcome ;-)

    >
    > I'm CC'ing this to Marshall Cline; this FAQ item wasn't meant to create
    > the impression you got (note that at the very start it mentions "except


    I don't think I got a wrong impression. The very reason I snipped your
    example was because you were correct in saying that I could still create an
    array if I gave an initializer and _no_ default constructor. There was
    nothing to nitpick there ;-) But still one needs to take the trouble to
    initialize each member, isn't that a pain ?

    > as discussed below"). In short, the correct version is that you can't
    > create an array of objects of a class type that has no default
    > constructor unless (a) an array initializer is given (the FAQ item gives
    > an example of that at the end, essentially the same example that I gave


    I think FAQ is correct here. It does say "except as discussed below" at the
    start as you also point out.

    > and you snipped but without the typos... ;-) ), or (b) placement new is
    > used, as it is internally in std::vector. Point (b) should perhaps be
    > mentioned directly in this FAQ item, and both points placed at the top.


    Do you mind giving one example of point b ?

    -Sharad
     
    Sharad Kala, Jul 25, 2004
    #9
  10. * Sharad Kala:
    >
    > "Alf P. Steinbach" <> wrote in message
    > news:...
    > > * Sharad Kala:
    > > >

    > [snip]
    > > > Read the FAQ -

    > http://www.parashift.com/c -faq-lite/ctors.html#faq-10.5
    > >
    > > Thank you.

    >
    > Most welcome ;-)
    >
    > >
    > > I'm CC'ing this to Marshall Cline; this FAQ item wasn't meant to create
    > > the impression you got (note that at the very start it mentions "except

    >
    > I don't think I got a wrong impression. The very reason I snipped your
    > example was because you were correct in saying that I could still create an
    > array if I gave an initializer and _no_ default constructor. There was
    > nothing to nitpick there ;-) But still one needs to take the trouble to
    > initialize each member, isn't that a pain ?
    >
    > > as discussed below"). In short, the correct version is that you can't
    > > create an array of objects of a class type that has no default
    > > constructor unless (a) an array initializer is given (the FAQ item gives
    > > an example of that at the end, essentially the same example that I gave

    >
    > I think FAQ is correct here. It does say "except as discussed below" at the
    > start as you also point out.


    I wasn't referring to the FAQ as incorrect in this regard. I was
    referring to your original unqualified claim that

    <quote>
    When you want to create an array of objects of your class. You can't
    do so in the absence of a default constructor.
    </quote>



    > > and you snipped but without the typos... ;-) ), or (b) placement new is
    > > used, as it is internally in std::vector. Point (b) should perhaps be
    > > mentioned directly in this FAQ item, and both points placed at the top.

    >
    > Do you mind giving one example of point b ?


    It's a bit of work to do correctly. Modulo alignment issues and
    exception issues and whatnot (omitted here... ;-) ) it goes like

    #include <new>

    class Point{ ... };

    int main()
    {
    size_t const nObjects = 54;
    char memory[nObjects*sizeof( Point )];
    Point* pObjects = 0;

    // Initialize array.
    char *pMem = memory;
    for( size_t i = 0; i < nObjects; ++i )
    {
    Point* pNew = ::new( pMem ) Point( i, -i ); // Whatever.
    if( pObjects == 0 ) { pObjects = pNew; }
    pMem += sizeof( Point );
    }

    // Use it.
    // Whatever, e.g.
    for( size_t i = 0; i < nObjects; ++i )
    {
    // std::cout << pObjects.x() << std::endl;
    }

    // Destroy.
    Point* pObj = pObjects;
    for( size_t i = 0; i < nObjects; ++i, ++pObj )
    {
    pObject->~Point(); // Modulo syntax, check it out.
    }
    }

    I can't really think of any situation where an application programmer
    would want to do this, but low-level library is another matter.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #10
  11. highli

    Sharad Kala Guest

    "Alf P. Steinbach" <> wrote in message
    news:...
    > * Sharad Kala:

    [snip]
    > It's a bit of work to do correctly. Modulo alignment issues and
    > exception issues and whatnot (omitted here... ;-) ) it goes like


    Quite good but not quite ;-)

    > #include <new>
    >
    > class Point{ ... };
    >
    > int main()
    > {
    > size_t const nObjects = 54;
    > char memory[nObjects*sizeof( Point )];
    > Point* pObjects = 0;
    >
    > // Initialize array.
    > char *pMem = memory;
    > for( size_t i = 0; i < nObjects; ++i )
    > {
    > Point* pNew = ::new( pMem ) Point( i, -i ); // Whatever.
    > if( pObjects == 0 ) { pObjects = pNew; }
    > pMem += sizeof( Point );
    > }
    >
    > // Use it.
    > // Whatever, e.g.
    > for( size_t i = 0; i < nObjects; ++i )
    > {
    > // std::cout << pObjects.x() << std::endl;
    > }
    >

    The following is not the way arrays would destruct.

    > // Destroy.
    > Point* pObj = pObjects;
    > for( size_t i = 0; i < nObjects; ++i, ++pObj )
    > {
    > pObject->~Point(); // Modulo syntax, check it out.
    > }

    Instead something like -
    // Destroy.
    Point* pObj = pObjects + sizeof(nObjects*sizeof( Point ));
    for( size_t i = 0; i < nObjects; ++i, --pObj )
    {
    pObjects->~Point(); // Modulo syntax, check it out.
    }
    Right, Alf ?

    -Sharad
     
    Sharad Kala, Jul 25, 2004
    #11
  12. * Sharad Kala:
    >
    > "Alf P. Steinbach" <> wrote in message
    > news:...
    > > * Sharad Kala:

    > [snip]
    > > It's a bit of work to do correctly. Modulo alignment issues and
    > > exception issues and whatnot (omitted here... ;-) ) it goes like

    >
    > Quite good but not quite ;-)
    >
    > > #include <new>
    > >
    > > class Point{ ... };
    > >
    > > int main()
    > > {
    > > size_t const nObjects = 54;
    > > char memory[nObjects*sizeof( Point )];
    > > Point* pObjects = 0;
    > >
    > > // Initialize array.
    > > char *pMem = memory;
    > > for( size_t i = 0; i < nObjects; ++i )
    > > {
    > > Point* pNew = ::new( pMem ) Point( i, -i ); // Whatever.
    > > if( pObjects == 0 ) { pObjects = pNew; }
    > > pMem += sizeof( Point );
    > > }
    > >
    > > // Use it.
    > > // Whatever, e.g.
    > > for( size_t i = 0; i < nObjects; ++i )
    > > {
    > > // std::cout << pObjects.x() << std::endl;
    > > }
    > >

    > The following is not the way arrays would destruct.
    >
    > > // Destroy.
    > > Point* pObj = pObjects;
    > > for( size_t i = 0; i < nObjects; ++i, ++pObj )
    > > {
    > > pObject->~Point(); // Modulo syntax, check it out.
    > > }

    > Instead something like -
    > // Destroy.
    > Point* pObj = pObjects + sizeof(nObjects*sizeof( Point ));
    > for( size_t i = 0; i < nObjects; ++i, --pObj )
    > {
    > pObjects->~Point(); // Modulo syntax, check it out.
    > }
    > Right, Alf ?


    Yep, mea culpa (while in nitpicking mode: s/pObjects/pObj/).

    Now there's only alignment (perhaps easier to fix the spec by
    requiring dynamic allocation) and exceptions (thorny) and the
    "whatnot" -- I'm not really sure -- to deal with... ;-)

    std::vector has it much easier since for a compiler-specific
    implementation it can rely on knowledge of, say, the internal
    workings of operator delete[], and so avoid both the loop and
    keeping track of the way the array was formed, but it's limited
    in that it doesn't support per-object-specific arguments.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #12
  13. * Alf P. Steinbach:
    > * Sharad Kala:
    > > > }

    > > Instead something like -
    > > // Destroy.
    > > Point* pObj = pObjects + sizeof(nObjects*sizeof( Point ));
    > > for( size_t i = 0; i < nObjects; ++i, --pObj )
    > > {
    > > pObjects->~Point(); // Modulo syntax, check it out.
    > > }
    > > Right, Alf ?

    >
    > Yep, mea culpa (while in nitpicking mode: s/pObjects/pObj/).


    And you also need to decrement pObj _before_ destructor call, and
    to be really standard-compliant make sure it isn't decremented
    last time out of the loop, and your address computation is very
    wrong (I tend to assume such things are OK when scanning code
    because if not then we usually know it), so it should look like

    Point* pObj = pObjects + nObjects; // Past 1 is allowed.
    for( size_t i = 0; i < nObjects; ++i )
    {
    --pObj;
    pObj->~Point();
    }

    Hth.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #13
  14. highli

    Sharad Kala Guest

    "Alf P. Steinbach" <> wrote in message
    news:...
    > * Alf P. Steinbach:
    > > * Sharad Kala:
    > > > > }
    > > > Instead something like -
    > > > // Destroy.
    > > > Point* pObj = pObjects + sizeof(nObjects*sizeof( Point ));
    > > > for( size_t i = 0; i < nObjects; ++i, --pObj )
    > > > {
    > > > pObjects->~Point(); // Modulo syntax, check it out.
    > > > }
    > > > Right, Alf ?

    > >
    > > Yep, mea culpa (while in nitpicking mode: s/pObjects/pObj/).

    >
    > And you also need to decrement pObj _before_ destructor call, and
    > to be really standard-compliant make sure it isn't decremented
    > last time out of the loop, and your address computation is very
    > wrong (I tend to assume such things are OK when scanning code
    > because if not then we usually know it), so it should look like


    oh yeah, that address calculation was bogus ;-)

    > Point* pObj = pObjects + nObjects; // Past 1 is allowed.
    > for( size_t i = 0; i < nObjects; ++i )
    > {
    > --pObj;
    > pObj->~Point();
    > }


    Still simpler -

    Point* pObj = pObjects + nObjects; // Past 1 is allowed.
    while( pObj != pObjects )
    {
    --pObj;
    pObj->~Point();
    }

    -Sharad
     
    Sharad Kala, Jul 25, 2004
    #14
  15. Alf P. Steinbach wrote in news: in
    comp.lang.c++:

    > Point* pObj = pObjects + nObjects; // Past 1 is allowed.
    >



    No the real array is char, so the above is "past sizeof( Point )"

    :).

    nitpicking-ly yr's Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
     
    Rob Williscroft, Jul 25, 2004
    #15
  16. * Sharad Kala:
    > Still simpler -
    >
    > Point* pObj = pObjects + nObjects; // Past 1 is allowed.
    > while( pObj != pObjects )
    > {
    > --pObj;
    > pObj->~Point();
    > }


    Well, that does one extra comparison compared to a do-while (assuming
    nObjects > 0), yes? </g>

    I like for-loops:

    for( Point* p=pObjects+nObjects; (--p)->~Point(); p!=pObjects )
    {}

    (still modulo syntax)...

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #16
  17. * Alf P. Steinbach:
    > * Sharad Kala:
    > > Still simpler -
    > >
    > > Point* pObj = pObjects + nObjects; // Past 1 is allowed.
    > > while( pObj != pObjects )
    > > {
    > > --pObj;
    > > pObj->~Point();
    > > }

    >
    > Well, that does one extra comparison compared to a do-while (assuming
    > nObjects > 0), yes? </g>
    >
    > I like for-loops:
    >
    > for( Point* p=pObjects+nObjects; (--p)->~Point(); p!=pObjects )
    > {}
    >
    > (still modulo syntax)...


    No fish biting here. Umph.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #17
  18. * Rob Williscroft:
    > Alf P. Steinbach wrote in news: in
    > comp.lang.c++:
    >
    > > Point* pObj = pObjects + nObjects; // Past 1 is allowed.
    > >

    >
    >
    > No the real array is char, so the above is "past sizeof( Point )"
    >
    > :).
    >


    Heh. I don't know whether the Holy Standard covers this situation
    or not. But practically, both "1 past end" pointers here refer to
    the same address, because the character array is sized just so.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 25, 2004
    #18
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Aire
    Replies:
    3
    Views:
    482
    Mike Wahler
    Jan 25, 2004
  2. Replies:
    9
    Views:
    986
    Alf P. Steinbach
    Mar 6, 2006
  3. Replies:
    4
    Views:
    429
    Salt_Peter
    Oct 12, 2006
  4. Replies:
    17
    Views:
    523
    Pete Becker
    Jan 14, 2007
  5. Generic Usenet Account
    Replies:
    10
    Views:
    2,313
Loading...

Share This Page