views:

122

answers:

5

I'm inheriting a class and I would like to call one of its constructors. However, I have to process some stuff (that doesn't require anything of the base class) before calling it. Is there any way I can just call it later instead of calling it on the initializer list? I believe this can be done in Java and C# but I'm not sure about C++.

The data that I need to pass on the constructor can't be reassigned later, so I can't just call a default constructor and initialize it later.

+9  A: 

Is there any way I can just call it later instead of calling it on the initializer list?

No, you cannot. The base class constructor must be called in the initializer list, and it must be called first.

In fact, if you omit it there, the compiler will just add the call implicitly.

I believe this can be done in Java and C# but I'm not sure about C++.

Neither C# nor Java allow this either.

What you can do, however, is call a method as an argument of the base class constructor call. This is then processed before the constructor:

class Derived {
public:
    Derived() : Base(some_function()) { }

private:
    static int some_function() { return 42; }
};
Konrad Rudolph
Thanks, didn't thought about just calling a function, so that'll work but it's going to be a bit messy because the constructor has 2 parameters. I'll accept this answer when I can (unless a better one comes out, of course). BTW, you're right about not being able to do this in Java and C#, I tought it was possible in Java because it's done using `super(...)` on the method body, but I've noticed now that it must be the first line.
placeholder
+1 You should make some_function() static to document the fact that it does not use any of the instance variables of the class (that have not been initialized).
Martin York
Interesting, never seen that done before. I presume the function called can be a derived class function.
PatrickV
@Patrick: It can be derived but it mustn’t be virtual and it mustn’t access member variables or the `this` pointer.
Konrad Rudolph
@Konrad Rudolph: Is the restriction on member variables a hard-restriction, or is it just a really bad idea?
PatrickV
@Patrick: The compiler won’t necessarily warn you but it really is a hard restriction since the object doesn’t exist yet, so neither do its members. Before the constructor was called, their values are simply memory garbage, and additionally you cannot even really access them since the `this` pointer doesn’t exist yet, and that is needed to calculate the location of the member variables.
Konrad Rudolph
A: 
struct base{
   base(int x){}
};

struct derived : base{
   derived(int x) : base(x){}
};

This is how base class constructors are invoked in C++ from the initialization list of derived class.

Chubsdad
This is not what he is asking.
Prasoon Saurav
+1  A: 

IMHO I dont think it is possible to defer calling the base class constructor in the way that you mentioned.

Als
A: 

If you have full control over the base class, I'd recommend adding a protected method to do the class initialization, make it virtual, and put the your derived class implementation details in it before it calls its base:

class Base
{
public:
    Base()
    {
        Initialize();
    }
protected:
    virtual void Initialize()
    {
        //do initialization;
    }
};

class Derived : Base
{
public:

    Derived() : Base()
    {
    }
protected:
    virtual void Initialize()
    {
        //Do my initialization
        //call base
        Base::Initialize();
    }
};
PatrickV
Unfortunately, I don't have control of the base class.
placeholder
You may not be able to meet your goal then. If you post more code, we might be able to come up with something, but I've never seen that done in C++.
PatrickV
I don't like the idea. Two-phase construction is always error-prone.
sbi
@sbi: Feel free to "not like it"... but if you need to access member data in c++ before the base class initialization, it is pretty much your only option. At least the only one I know of. I wish there was a cleaner solution, but this is the cleanest solution I know of. The question asker may not need member data access, but another reader that comes across this might, and it is much cleaner than adding a static function to the class IMO.
PatrickV
@PatrickV: I have posted a working solution that doesn't need two-phase construction. Granted, sometimes two-phase construction seems easier. But if I would ever use it, I'd certainly hide it behind an object with a simple constructor. Well, thinking of it, basically that's what my solution does...
sbi
@sbi: It's neat, but I don't like that approach. I hadn't thought of it, and glad you posted it so I gave you a +1, but using multiple inheritance to solve this problem? When you inherit from something, you need to be able to stand before the president of your company and say outloud "class A is a class B". In this case, you'd say "the_class" is primarily a "my_dirty_little_secret" and also a "the_other_base_class". Just to fool the construction? There's probably a place for both solutions. I believe only one of these is portable to C#. Not sure on that though, still learning it.
PatrickV
@PatrickV: You're confusing public and private inheritance. Public inheritance describes an Is-A relationship, private doesn't. I suggest you [read up on the subject](http://www.parashift.com/c++-faq-lite/private-inheritance.html).
sbi
@sbi I'm fully read up on that subject. I suggest you go back and read my last post a little more carefully.
PatrickV
@PatrickV: Sorry, but that's to vague for me. You wrote "the_class is primarily a my_dirty_little_secret". That's simply wrong. I was referring to that in my explanation. What are you referring to?
sbi
@sbi: Sorry, was on vacation. I guess what I was getting at was that your approach complicates the design of the software from an inheritance perspective when compared to mine. Both have their merit. It just depends on your situation. I know that doing what you proposed would have to make it on my class inheritance diagrams, and at that level, we want those diagrams as simples as possible. I'd much prefer what you describe as "error-prone" two phase construction if it simplifies the design. And again, I don't think that approach is portable to C#. But I'd love to be wrong on that.
PatrickV
@PatrickV: Whoever forces you to put _private_ inheritance on a derivation chart should be offered to read an introductory C++ book or be dragged out of the room and silently shot. Private inheritance is the same as private data: it's nobody's business but the class's implementer and friends.
sbi
@sbi: That is an unfortunate tool limitation. The wonders of working with the latest technology 1997 had to offer. Your tax dollars at work! (well, some of you at least) That's the real world problem some of us deal with - the design tool forces that on the diagram, which forces that on the report, which gets auto-put in the slide show, which goes before the chief *system* architect who may or may not understand private inheritance. In my case, the 2-step construction is wiser option. The more tools you hae in the toolbox, the better off you are.
PatrickV
@PatrickV: While pesky office politics, and arbitrary limitations of some tool(s) you have to use as a result of that, might make it easier for you to write harder-to-maintain code, that doesn't mean that it is better to do so in general.
sbi
@sbi: Let it go, indiana.
PatrickV
Oh well, tried to edit that, but it won't let me. That will probably come off as a prickish response - one of our thrown out 50 times a day sayings at the office. If it offends, sbi, I apologize. My point was - I've heard your side of the debate, and disagree. Rehashing the same point again is not going to make me agree. It's OK that we disagree - now lets get back to helping those in need.
PatrickV
+3  A: 

As was said by several people answering, you cannot delay the invocation of a base class constructor, but Konrad has given a good answer that might well solve your problem. However, this does have its drawbacks (for example, when you need to initialize several functions with values whose calculations share intermediate results), so just to be complete, here's another way of solving the problem of fixed initialization order, by using it.

Given the fixed order of initialization, if you have control over the derived class (and how else would you come to fiddle with one of its ctors?), you can sneak in a private base so that it is going to be initialized before the other base, which can then be initialized with the private base's already calculated values:

class my_dirty_little_secret {
  // friend class the_class;
  my_dirty_little_secret(const std::string& str)
  {
    // however that calculates x, y, and z from str I wouldn't know
  }
  int x;
  std::string y;
  float z;
};

class the_class : private my_dirty_little_secret // must be first, see ctor
                , public the_other_base_class {
  public:
    the_class(const std::string str)
      : my_dirty_little_secret(str)
      , the_other_base_class(x, y, z)
    {
    }
  // ...
};

The my_dirty_little_secret class is a private base so that users of the_class cannot use it, all of its stuff is private, too, with explicit friendship granting only the_class access to it. However, since it's listed first in the base class list, it will reliably be constructed before the_other_base_class, so whatever it calculates can be used to initialize that.
A nice comment at the base class list hopefully prevents from others breaking things by refactoring.

sbi