25

As far as I know it is not possible to call the constructor of the base class. The only way I know is this:

MyClass::MyClass(/* args */) : Base(/* args */)
{
   // ...
}

but this would invoke the constructor at the beginning. Is there any way to call it somewhere else in the constructor? Something like this:

MyClass::MyClass(/* args */)
{
   // ... instructions
   Base::Base(/* args */);
   // ... other_instructions
}

According to this What are the rules for calling the superclass constructor? question I understand there is no way but I read here and I guessed it was possible, but if I try I get:

error: invalid use of 'class Base'.

Am I doing something wrong? Is it possible to do this some way or is there any other possible solution to this need?

Thanks!

EDIT: I understand I forgot a key point: the base class is part of a framework, and therefore it would be good not to have to modify it, if possible.

Community
  • 1
  • 1
Luca Carlon
  • 9,546
  • 13
  • 59
  • 91
  • 1
    The question is: *Why do you need this?* – Björn Pollex May 05 '11 at 08:49
  • for some reason I cannot retag this question, adding OOP as a tag would be approppriate I think. – amit May 05 '11 at 08:59
  • I need this because I need to modify a class of the Qt framework, but I would like to avoid having to modify the Qt source code directly. It seems than the constructor of a widget does something that result in calling some a method in a Qt driver. Before this call occurs, I would like to have some other fields I added already initialized. – Luca Carlon May 05 '11 at 12:49
  • It's perfectly valid and in my opinion one of the stranger things in C++ that you cannot do that. In Swift it is compiler enforced that the subclass's local variables must be instantiated before you can call super's constructor. – Trenskow Jan 10 '23 at 16:24

7 Answers7

20

If the base class constructor takes at least one argument, you could use a helper function like this:

int DoStuffBeforeCtorAndForwardInt(int arg, Foo foo)
{
    DoStuff(arg, foo);
    return arg;
}

MyClass::MyClass(int arg, Foo foo)
    : Base(DoStuffBeforeCtorAndForwardInt(arg, foo))
{
   // ...
}

If you want to default-initialize the base class, you could use the copy-ctor to copy a default initialized base class instance:

Base DoStuffBeforeCtorAndReturnDefaultBase(int arg, Foo foo)
{
    DoStuff(arg, foo);
    return Base();
}

MyClass::MyClass(int arg, Foo foo)
    : Base(DoStuffBeforeCtorAndReturnDefaultBase(arg, foo))
{
   // ...
}

Or, if Base doesn't have to be the first base class, you could derive MyClass from a helper class:

MyClass::MyClass(/* ... */)
    : DoStuffHelperClass(/* ... */),
    Base(/* ... */)
{
   // ...
}

All of the above require that the "stuff" you do does not depend on the object that's about to be initialized (i.e. the functions can't safely be member functions and you cannot safely pass this as an argument to them either).

That means you can do some logging or similar, but then again you could also do that after the base class has been initialized.

(EDIT except with the DoStuffHelperClass solution, you can of course have members in DoStuffHelperClass, access them and what not)


Although I have to say that I can't recall ever using/needing/wanting something like that. It's quite probable that there is another (preferable) solution for what you're trying to do.

Paul Groke
  • 6,259
  • 2
  • 31
  • 32
  • I don't know if these solutions will actually work in what I'm trying to do, but anyway it seems to me each of these are excellent answers to my question! Thanks! – Luca Carlon May 07 '11 at 08:34
10

Use the base-from-member idiom to run your code before the ctor of the "real" base class (which is Base):

struct Base {
  Base(string, int);
};

struct DerivedDetail {
  DerivedDetail() {
    value = compute_some_value();
    value += more();
    value += etc();
    other = even_more_code(value);
  }
  string value;
  int other;
};

struct Derived : private DerivedDetail, Base {
  Derived() : Base(value, other) {}
  // In particular, note you can still use this->value and just
  // ignore that it is from a base, yet this->value is still private
  // within Derived.
};

This works even if you don't have actual members you want in DerivedDetail. If you give more specifics on what you must do before the Base's ctor, then I can give a better example.

Fred Nurk
  • 13,952
  • 4
  • 37
  • 63
8

The base class is always fully constructed before construction of your own class begins. If you need to make a change to the state of the base class, you have to do that explicitly after it has been constructed.

Example:

MyClass::MyClass()
{
    // Implicit call to Base::Base()

    int result = computeSomething();
    Base::setResult(result);

    // ... 
}
Lstor
  • 2,265
  • 17
  • 25
2

Besides the already written solutions, you can also use a static constructor function and make the contructor of MyClass private.

class QtBase{
  // ...
};

class MyClass : public QtBase{
public:
  // copy ctor public
  MyClass(MyClass const& other);

  static MyClass Create(/*args*/){
    // do what needs to be done
    int idata;
    float fdata;
    // work with idata and fdata as if they were members of MyClass
    return MyClass(idata,fdata); // finally make them members
  }

  static MyClass* New(/*args*/){
    int idata;
    float fdata;
    // work with idata and fdata as if they were members of MyClass
    return new MyClass(idata,fdata); // finally make them members
  }

private:
  // ctor private
  MyClass(int a_idata, float a_fdata)
    : idata(a_idata)
    , fdata(a_fdata)
  {}

  int idata;
  float fdata;
};

Now you would have to create instances of MyClass either as:

MyClass obj = MyClass::Create(/*args*/);

or

MyClass* ptr = MyClass::New(/*args*/);
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • BTW: that's called the "Named Constructor Idiom" ;) – Paul Groke May 05 '11 at 13:30
  • If I'm understanding correctly this would be a solution if I didn't need to initialize members of my subclass. I can't do that with this solution, right? Thanks! – Luca Carlon May 05 '11 at 22:07
  • @Luca: Well, you can always have a constructor that takes his members already initialized. :) – Xeo May 05 '11 at 22:09
  • Sorry, this means I'm not understanding this solution :-) If I'm instantiating MyClass in the return statement, in "do what needs to be done" I can do nothing to access members of the instance of MyClass. But maybe I'm completely missing the point... Can you make an example? Thanks for your help! – Luca Carlon May 06 '11 at 21:49
  • @Luca: Edited the answer a bit, added dummy member data. What I meant was, you prepare the member data and pass it to the constructor like shown with comments. – Xeo May 06 '11 at 21:59
  • Ah I see! Ok! This seems OK as well! Another possible solution! Thanks! – Luca Carlon May 07 '11 at 08:38
0

no, because it will not be type safe.
consider you have: a class A and a variable A.var.
now consider B inherits from A, and uses var before A was initialized. you will get a run time error! the language wants to prevent this, thus superclass constructor must be initialized first.

amit
  • 175,853
  • 27
  • 231
  • 333
0

No, you can't do it that way, as other have described in their previous answers.

Your only chance is composition, IOW that MyClass uses Base class as a member field:

class MyClass {
public:
   /** the methods... */

private:
   Base* _base;
};

so you can initialize _base later, when you have the needed info. I don't know if this can apply to your scenario, anyway.

Simone
  • 11,655
  • 1
  • 30
  • 43
  • Unfortunately I think my only possibility is to create an actual subclass. The method that is invoked is passed the instance I'm creating as a parameter, and there I need my subclass. – Luca Carlon May 06 '11 at 21:54
-1

No. It is not possible, because the order of constructor calls is strictly defined by the standard. Base class ctor has to be executed before the derive class ctor can be executed.