Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Question: Constructors in C++

Options
  • 27-01-2004 3:28pm
    #1
    Closed Accounts Posts: 43


    I know that in Java when you have multiple constructors in one class, you can call a constructor from within another constructor (e.g. a default constructor with no arguments can call a more explicit constructor with some default arguments).

    I can't seem to get the same thing to happen in C++. What I'm trying is something along the lines of this (assume Ass is the class name):


    Ass::Ass() { // Default constructor
    ...Ass::Ass( <whatever arguments> );
    }

    .....

    Ass::Ass( <whatever arguments> ) {
    ...// implementation
    }



    I got into trouble when creating instances of this class; I'm guessing that the default constructor creates a local instance of Ass that goes out of scope when the default constructor completes. In effect, the default constructor does nothing.

    Am I right in this guess?
    And how may I get around it.

    Thanks in advance!


Comments

  • Registered Users Posts: 6,309 ✭✭✭OfflerCrocGod


    What are you trying to achive???!! could you post the code up. I dont know wheter what you are trying to do is a good idea or not......just something about it I dont like. What's the point?, why not just make a constructor that does what you want without having to go through another constructor.


  • Registered Users Posts: 1,931 ✭✭✭Zab


    Use "this()" instead of "Ass::Ass( <whatever arguments> )". It will have to be on the first line of the constructor.

    Zab.


  • Registered Users Posts: 3,312 ✭✭✭mr_angry


    Yeah, the "this" pointer is your friend, but I'd imagine that calling another constructor from within the original constructor is bad practice. Plus, I'm pretty sure you're creating at least 2 instances of the class for a given call to that constructor, no?


  • Registered Users Posts: 1,931 ✭✭✭Zab


    No, calling a constructor from within another constructor is both good practice and common. Depending, of course, on what you are trying to achieve. And you are only creating one instance.


  • Registered Users Posts: 6,309 ✭✭✭OfflerCrocGod


    Originally posted by Zab
    No, calling a constructor from within another constructor is both good practice
    How?:confused:


  • Advertisement
  • Registered Users Posts: 3,312 ✭✭✭mr_angry


    Originally posted by Zab
    No, calling a constructor from within another constructor is both good practice and common. Depending, of course, on what you are trying to achieve. And you are only creating one instance.

    I suppose it depends when the "new" function is invoked. I would still question it being good practice though, whether or not it is common. In the case of a superclass, I can understand, but in the same class I would think you should be refactoring common functionality into a private member function all of its own.


  • Registered Users Posts: 79 ✭✭tendofan


    Isn't it often better to use default arguments for your constructor?

    class C
    {
    public:
    C(int a=0, int b=0, int c=0) : m_a(a), m_b(b), m_c(c)
    {
    }

    private:
    int m_a;
    int m_b;
    int m_c;
    };

    because then you can construct instances of the object like this:

    C x; //same as C(0,0,0);
    C y(1); //same as C(1, 0, 0);
    C z(1,2); //same as C(1,2,0);
    C w(1, 2, 3); //same as C(1, 2, 3)

    Tendofan


  • Closed Accounts Posts: 43 Kid Icarus


    Originally posted by Zab
    Use "this()" instead of "Ass::Ass( <whatever arguments> )". It will have to be on the first line of the constructor.
    This is what I was looking for. I believe this to be good practice; it's more common in Java than C++ from what I've seen though.
    Originally posted by tendofan
    class C
    {
    public:
    C(int a=0, int b=0, int c=0) : m_a(a), m_b(b), m_c(c)
    {
    }

    private:
    int m_a;
    int m_b;
    int m_c;
    };

    because then you can construct instances of the object like this:

    C x; //same as C(0,0,0);
    C y(1); //same as C(1, 0, 0);
    C z(1,2); //same as C(1,2,0);
    C w(1, 2, 3); //same as C(1, 2, 3)
    But this works even better. I had 5 constructors, the 5th being the most explicit with 4 arguments. Each of the other 4 constructors used one more argument than the previous; all of the constructors used the last constructor with some default values. The code above allows me to do all this in one constructor. Nice!

    Thanks to all who replied.


  • Registered Users Posts: 1,372 ✭✭✭silverside


    could someone please provide a code sample illustrating Zab's solution? I am trying the suggestion of calling this() within the overloaded constructor but it isn't compiling for me in VC++7

    Thanks

    s.


  • Closed Accounts Posts: 30 Lu[ifer


    Using C++ and this , the original code becomes....

    [php]
    Ass::Ass() { // Default constructor
    this->ASS( <whatever arguments> );
    }

    .....

    Ass::Ass( <whatever arguments> ) {
    ...// implementation
    }
    [/php]

    note, using this is actually optional. could have simply written
    [PHP]ASS( <whatever arguments> );[/PHP]
    as this is implicitly implied.

    Also, on the point of whether or not this is good practice, i think that it is ok.
    I agree with tendofan that using default parameters is nicer, but i point out that in c# this is not possible (and creating overloaded constructors is recommended).


  • Advertisement
  • Registered Users Posts: 1,931 ✭✭✭Zab


    After rereading this thread, I've realised that I'm doing way too much Java these days. I've got a sinking feeling that this won't work in C++ at all. Calling Ass(args) definately won't work anyway, as it will create a new object, initialize it and soon destruct it. I also have a feeling that this->Ass() and this() won't compile either. As pointed out, this is how you would do things in Java, and some other OO languages. Anyway, sorry if I mislead you, and you should go with one of the other options mentioned here.


  • Closed Accounts Posts: 30 Lu[ifer


    Zab, I believe you're mistaken.

    Calling Ass(args) won't create a new instance.
    To create a new instance you need to write either

    Ass myAss(args); // or
    Ass* p_myAss = new Ass(args);

    Calling Ass() within one constructor, is the same as calling any other method and seems perfectaly acceptable.

    As a correction to my previous post, it seems you cannot write this->Ass(), but should simply write Ass().


  • Registered Users Posts: 1,372 ✭✭✭silverside


    Yep it works allright, thanks for the help, makes my code a little bit neater !


  • Closed Accounts Posts: 9,314 ✭✭✭Talliesin


    I scanned the standard and I'm not sure if any of this is guaranteed by it, so I'd be cautious.

    It occurred to me that perhaps something like:

    class c{
    /*elide private members*/
    public:
    c(int x, int y);
    c(int x)
    {
    new(this) c(x, x);
    }
    };

    Would work and match the standard's guarantees, though it seems a bit dicey as well.

    The biggest problem I see in this though, is that whether or not it is okay by the standard it can't work with member initialisation lists, which may encourage one away from using them - even to the point where one slightly changes the classes safety (say, by making a const member non-const just for the sake of a more convenient collection of constructors).
    Because of this I'd tend towards having constructors call a private member function rather than calling each other - after the member initialisation list has been processed.


Advertisement