implicit constructor declaration (user annoyed)

Discussion in 'C++' started by sb, Feb 23, 2004.

  1. sb

    sb Guest

    If there is at least one user-defined constructor, no constructors are
    implicitly declared.

    struct my_vec : public vector<int> {
    double foo;
    my_vec(size_t n) : vector<int>(2*n) {}
    // oops, no default ctor any more
    // have to do a lot of stupid typing now , like:
    my_vec() : vector<int>() {}
    // etc.
    };

    Does anyone else find this behavior annoying? Instead, I would prefer
    for the compiler to implicitly declare all constructors that are not
    declared by the user.
     
    sb, Feb 23, 2004
    #1
    1. Advertising

  2. "sb" <> wrote in message
    news:...
    > If there is at least one user-defined constructor, no constructors are
    > implicitly declared.
    >
    > struct my_vec : public vector<int> {
    > double foo;
    > my_vec(size_t n) : vector<int>(2*n) {}
    > // oops, no default ctor any more
    > // have to do a lot of stupid typing now , like:
    > my_vec() : vector<int>() {}
    > // etc.
    > };
    >
    > Does anyone else find this behavior annoying? Instead, I would prefer
    > for the compiler to implicitly declare all constructors that are not
    > declared by the user.


    Personally I would prefer no constructors to be implicitly defined. But I
    think the purpose behind the rules as they are is to define the minimum
    implicit constructors will remaining compatible with C.

    E.g. this code has to compile as C and C++.

    // C code
    typedef struct
    {
    int x;
    } X;

    X x; // use of implicit default constructor
    X y = x; // use of implicit copy constructor

    As soon as you define one constructor, you are no longer compatible with C
    anyway, so the rules can be tightened.

    john
     
    John Harrison, Feb 23, 2004
    #2
    1. Advertising

  3. "John Harrison" <> wrote in message
    news:c1duao$1hsqre$-berlin.de...
    >
    > "sb" <> wrote in message
    > news:...
    > > If there is at least one user-defined constructor, no constructors are
    > > implicitly declared.
    > >
    > > struct my_vec : public vector<int> {
    > > double foo;
    > > my_vec(size_t n) : vector<int>(2*n) {}
    > > // oops, no default ctor any more
    > > // have to do a lot of stupid typing now , like:
    > > my_vec() : vector<int>() {}


    Actually you don't have to do that

    my_vec() {}

    is good enough, no too many keystrokes. Or even this

    my_vec(size_t n = 0) : vector<int>(2*n) {}

    And don't publically inherit from STL container classes, its bad form.

    john
     
    John Harrison, Feb 23, 2004
    #3
  4. sb

    Mike Wahler Guest

    "sb" <> wrote in message
    news:...
    > If there is at least one user-defined constructor, no constructors are
    > implicitly declared.
    >
    > struct my_vec : public vector<int> {
    > double foo;
    > my_vec(size_t n) : vector<int>(2*n) {}
    > // oops, no default ctor any more
    > // have to do a lot of stupid typing now , like:
    > my_vec() : vector<int>() {}
    > // etc.
    > };
    >
    > Does anyone else find this behavior annoying? Instead, I would prefer
    > for the compiler to implicitly declare all constructors that are not
    > declared by the user.


    struct my_vec : public vector<int> {
    double foo;

    public:
    my_vec(std::vector<int>::size_type n = 0) // default ctor
    : vector<int>(2*n) {} };
    };

    BTW why are you inheriting from std::vector?

    -Mike
     
    Mike Wahler, Feb 23, 2004
    #4
  5. sb wrote:
    > If there is at least one user-defined constructor, no constructors are
    > implicitly declared.
    >
    > struct my_vec: public vector<int> {

    private:
    > double foo;

    public:
    my_vec(size_t n = 0): vector<int>(2*n) { }
    > // etc.
    > };



    > Does anyone else find this behavior annoying?


    Not me.

    > Instead, I would prefer
    > for the compiler to implicitly declare all constructors
    > that are not declared by the user.
     
    E. Robert Tisdale, Feb 23, 2004
    #5
  6. sb wrote:
    > If there is at least one user-defined constructor, no constructors are
    > implicitly declared.
    > ...


    Not exactly true. Copy constructor is always implicitly declared (unless
    you explicitly declare copy constructor yourself). Explicit declaration
    of non-copy constructor will not suppress implicit declaration of copy
    constructor.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Feb 23, 2004
    #6
  7. sb

    Cy Edmunds Guest

    "sb" <> wrote in message
    news:...
    > If there is at least one user-defined constructor, no constructors are
    > implicitly declared.
    >


    You certainly wrote an unconvincing example:

    > struct my_vec : public vector<int> {


    deriving from std::vector ? ugh

    > double foo;


    public data member. ugh again

    > my_vec(size_t n) : vector<int>(2*n) {}


    this constructor converts integers to my_vec's because you neglected to
    declare it explicit

    > // oops, no default ctor any more
    > // have to do a lot of stupid typing now , like:


    I am tempted to say that you have already done a lot of stupid typing, but
    that wouldn't be a quality statement, so I won't. :)

    > my_vec() : vector<int>() {}


    my_vec() {} doesn't look so onerous

    > // etc.
    > };
    >
    > Does anyone else find this behavior annoying? Instead, I would prefer
    > for the compiler to implicitly declare all constructors that are not
    > declared by the user.


    Perhaps you are a bit too easily annoyed. This rule seems reasonable,
    doesn't stop anybody from doing what they want, and in any event is already
    established by many years of usage.

    --
    Cy
    http://home.rochester.rr.com/cyhome/
     
    Cy Edmunds, Feb 23, 2004
    #7
  8. sb

    sb Guest

    "John Harrison" <> wrote in message news:<c1dufk$1h4gl7$-berlin.de>...
    > "John Harrison" <> wrote in message
    > news:c1duao$1hsqre$-berlin.de...
    > >
    > > "sb" <> wrote in message
    > > news:...
    > > > If there is at least one user-defined constructor, no constructors are
    > > > implicitly declared.
    > > >
    > > > struct my_vec : public vector<int> {
    > > > double foo;
    > > > my_vec(size_t n) : vector<int>(2*n) {}
    > > > // oops, no default ctor any more
    > > > // have to do a lot of stupid typing now , like:
    > > > my_vec() : vector<int>() {}

    >
    > Actually you don't have to do that
    >
    > my_vec() {}
    >
    > is good enough, no too many keystrokes. Or even this
    >
    > my_vec(size_t n = 0) : vector<int>(2*n) {}


    The snippet is merely an illustration. It could have been

    my_vec(size_t n) : vector<int>(2*n + 1) {}

    >
    > And don't publically inherit from STL container classes, its bad form.


    Arghh! If I had a dime for every time I heard this...

    Should I use containment and redefine all methods instead? (lots and
    lots of stupid wrapper code). And what if I want my_vec to *BE* a
    vector<int> ? No "style" or "possible misuse" considerations will make
    up for such braindamage.

    I'm sure some people feel very productive when they write

    private:
    t m_foo;
    public:
    const t& foo() const { return m_foo; }
    t& foo() { return m_foo; }

    and then go on to replicate most of the contents of std::vector.
    Wheeee! Accessors! Const-correct ones! Wheee! 300 lines of code in one
    hour. The manager must be realy proud of me! Thanks. I think I'll
    pass.
     
    sb, Feb 24, 2004
    #8
  9. > > And don't publically inherit from STL container classes, its bad form.
    >
    > Arghh! If I had a dime for every time I heard this...
    >
    > Should I use containment and redefine all methods instead? (lots and
    > lots of stupid wrapper code). And what if I want my_vec to *BE* a
    > vector<int> ? No "style" or "possible misuse" considerations will make
    > up for such braindamage.
    >


    The only case I heard where someone convincingly argued for deriving from a
    standard container was a teacher who wanted a class exactly like std::string
    but wanted to catch null pointer errors, for the benefit of his students who
    were making that sort of error.

    Almost every time I see derivation from a standard container it is because
    someone wants to avoid the trouble of writing three of four wrapper methods
    and doesn't know or doesn't care that they are needlessly inheriting scores
    of methods from the parent class.

    So I'll revise my advice, don't inherit from std::vector unless you have
    good reason and you know what you are doing. I guess there is a small number
    of cases where you want a class with *exactly* the same interface as
    std::vector but with some additional behaviour, but I think its very rare.

    john
     
    John Harrison, Feb 24, 2004
    #9
  10. sb

    Cy Edmunds Guest

    "sb" <> wrote in message
    news:...
    > "John Harrison" <> wrote in message

    news:<c1dufk$1h4gl7$-berlin.de>...
    > > "John Harrison" <> wrote in message
    > > news:c1duao$1hsqre$-berlin.de...
    > > >
    > > > "sb" <> wrote in message
    > > > news:...
    > > > > If there is at least one user-defined constructor, no constructors

    are
    > > > > implicitly declared.
    > > > >
    > > > > struct my_vec : public vector<int> {
    > > > > double foo;
    > > > > my_vec(size_t n) : vector<int>(2*n) {}
    > > > > // oops, no default ctor any more
    > > > > // have to do a lot of stupid typing now , like:
    > > > > my_vec() : vector<int>() {}

    > >
    > > Actually you don't have to do that
    > >
    > > my_vec() {}
    > >
    > > is good enough, no too many keystrokes. Or even this
    > >
    > > my_vec(size_t n = 0) : vector<int>(2*n) {}

    >
    > The snippet is merely an illustration. It could have been
    >
    > my_vec(size_t n) : vector<int>(2*n + 1) {}
    >
    > >
    > > And don't publically inherit from STL container classes, its bad form.

    >
    > Arghh! If I had a dime for every time I heard this...
    >
    > Should I use containment and redefine all methods instead? (lots and
    > lots of stupid wrapper code). And what if I want my_vec to *BE* a
    > vector<int> ? No "style" or "possible misuse" considerations will make
    > up for such braindamage.
    >
    > I'm sure some people feel very productive when they write
    >
    > private:
    > t m_foo;
    > public:
    > const t& foo() const { return m_foo; }
    > t& foo() { return m_foo; }
    >
    > and then go on to replicate most of the contents of std::vector.
    > Wheeee! Accessors! Const-correct ones! Wheee! 300 lines of code in one
    > hour. The manager must be realy proud of me! Thanks. I think I'll
    > pass.


    If you are ever interviewing for a job, please make these opinions known to
    your interviewer. It might be me, and I certainly wouldn't want to hire you.

    --
    Cy
    http://home.rochester.rr.com/cyhome/
     
    Cy Edmunds, Feb 24, 2004
    #10
  11. sb

    Andre Heinen Guest

    On 23 Feb 2004 22:52:49 -0800, (sb) wrote:
    >
    >I'm sure some people feel very productive when they write
    >
    >private:
    > t m_foo;
    >public:
    > const t& foo() const { return m_foo; }
    > t& foo() { return m_foo; }
    >
    >and then go on to replicate most of the contents of std::vector.
    >Wheeee! Accessors! Const-correct ones! Wheee! 300 lines of code in one
    >hour. The manager must be realy proud of me! Thanks. I think I'll
    >pass.


    Actually those 300 lines of code can save you *lots* of time. If
    m_foo is public, what will happen when you will have to change
    your class's implementation? Imagine this:

    class T_Wrapper {
    // no const-correctness in this class because it isn't
    // what we're talking about
    public:
    T foo;
    void print() {
    string s = makeStringRepresentation();
    cout << s;
    }
    string makeStringRepresentation() {
    // lots of time-consuming processing here
    }
    };

    And in the client code:

    void f(T_Wrapper& tw) {
    tw.foo = someValue;
    tw.print();
    }

    One day you decide to optimize makeStringRepresentation():

    class T_Wrapper {
    public:
    T foo;
    string cachedStringRep;
    bool cacheIsUpToDate;
    void print() {
    if ( ! cacheIsUpToDate) {
    cachedStringRep = makeStringRepresentation();
    cacheIsUpToDate = true;
    }
    cout << cachedStringRep;
    }
    string makeStringRepresentation() {
    // same as above
    }
    void setFoo(T newFoo) {
    foo = newFoo;
    cacheIsUpToDate = false; // let's not forget this
    }
    };

    Well, now f() is broken, because it changes foo without setting
    cacheIsUpToDate to false. And so is all your client code. You
    have to rewrite (or at least check) *everything*.

    I think data members should be private even if they are part of
    the interface. Unless, of course, you have some good reason to
    do otherwise.

    And, by the way, const-correctness is useful too...
    ;-)

    --
    Andre Heinen
    My address is "a dot heinen at europeanlink dot com"
     
    Andre Heinen, Feb 25, 2004
    #11
    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. Sky Sigal
    Replies:
    3
    Views:
    1,680
    John Saunders
    Jul 16, 2004
  2. Jason
    Replies:
    3
    Views:
    12,013
    Thomas Mang
    Jan 1, 2004
  3. Andy
    Replies:
    2
    Views:
    1,620
    Matthew
    Jan 28, 2005
  4. Generic Usenet Account
    Replies:
    10
    Views:
    2,344
  5. Mike Schilling

    I'm annoyed

    Mike Schilling, Jul 31, 2008, in forum: Java
    Replies:
    9
    Views:
    368
Loading...

Share This Page