-2

Suppose I have a base class,

struct X{
     std::container<class> A;
     std::container<class> B;

     void do_this(...){...};
     void do_that(...){...};

     X(classC something){
          do_this(...);
          do_that(...);
     }
}

And I want to create a descendant, but I need to only change a couple of lines in one of the methods called in the constructor:

struct Y:X{
    void do_this(...){
         // make my changes
    }
}

Now, when I call Y(classC input), I should get my Y struct as intended, right?


How would I do this in C++?

Chris
  • 28,822
  • 27
  • 83
  • 158
  • I believe you want a [`virtual`](http://en.cppreference.com/w/cpp/language/virtual) function, but you [should avoid calling virtual functions in constructors](https://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors) – kmdreko Mar 06 '18 at 20:01
  • Can those members be placed in another class? – StoryTeller - Unslander Monica Mar 06 '18 at 20:01
  • @StoryTeller I don't think so? path of least resistance here is just for me to redo the constructor. If it is a difficult question to answer, and I need to use a lot of magic words in the code, then I'll just respect the downvote and move along – Chris Mar 06 '18 at 20:03
  • As long as `Y` inherits from `X` and `X` doesn't have a default constructor you should call it explicitly. – Raindrop7 Mar 06 '18 at 20:03
  • It's not difficult to answer, and I didn't downvote. I just want to know about your constraints. – StoryTeller - Unslander Monica Mar 06 '18 at 20:04
  • @StoryTeller oh, ok, yeah, the members reference items within the class, so they can't come out...or they could, but it would defeat the purpose, as I would be creating a lot of functions--would rather just copy paste at that point. – Chris Mar 06 '18 at 20:05

3 Answers3

2

Now, when I call Y(classC input), I should get my Y struct as intended, right?

Wrong. Inheriting a constructor doesn't mean its body is recreated with the function calls substituted by the ones you overload. It means that to construct a Y it is sufficient to construct the X sub-object explicitly via that c'tor. So rather than hassling you with forwarding stuff, you pull the appropriate c'tor into Y to be used.

This means, same c'tor body. And everything else that is Y specific will be default initialized.

How would I do this in C++?

Simply put, you can't do it easily. Unless you mess around with dark template magic, X::X will always call X::do_this. You could also move do_this to some other class, and use that one polymorphically, but as you mentioned, this isn't an option.

If you want to add a call to Y::do_this, then write a c'tor for Y. But it won't replace the call to X::do_this, it will happen afterwards. That's the C++ object model.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
1

As long as class Y inherits from class X and class X doesn't have a default constructor you must call its overloaded version explicitly in the overloaded class (Y):

class X{
    public:
        X(int _x) : x(_x){};
    private:
        int x;
};

class Y : public X{
    public:
        Y() : X(0){} // important
};


int main() {

    Y y; // if you remove the default constructor of Y you'll get an error here

    return 0;
}
Raindrop7
  • 3,889
  • 3
  • 16
  • 27
1

This is tough, because the only good method would be to use virtual functions. This is however not feasible here, because virtual methods in constructors are resolved statically. This means, that if you have class A and class B : A and both of them have implemented virtual function foo, when you call foo in base class constructor it will always use base class implementation.

The one method is to use it like this:

class A {
public:
    A(whatever) { }
    virtual void initialize() {
        // base class impl
    }
};
class B : public A{
public:
    // if no base default ctor, use
    // B(whatever)
    //     : A(whatever)
    B(whatever) {
    }
    virtual void initialize() override {
        // derived class impl
    }
};

template <typename T> // constraint it if you want.
T createObject() {
    T object;
    object.initialize(); // resolved dynamically
}
Poeta Kodu
  • 1,120
  • 8
  • 16
  • ah, I see what you are saying! makes sense that it wouldn't work, if that is how it is designed – Chris Mar 06 '18 at 20:20