1

Consider the following situation:

#include <iostream>
using namespace std;

class A {
  public:
    int y;
    A(int &x) {
        x = 2;
        y = 1;
    }
};

class B : public A {
  public:
    int *p;
    B(int t) : A(*p) {}
};

int main() {
    B b(2);
    return 0;
}

When the constructor of B is called, p has a junk value. So, when *p is to be passed to A(), it gives me a Segmentation Fault. I would want to initialize p = new int; before calling A(*p) - is this possible?

EDIT: Interestingly, calling B's constructor without arguments didn't give a segmentation fault.

piggs_boson
  • 987
  • 2
  • 12
  • 25
  • You have to inherit from class (before A) with `int*p` to do that. – Jarod42 Jun 04 '15 at 09:07
  • This code is not going to give you a segmentation fault. – T.C. Jun 04 '15 at 09:07
  • I assume it is a toy example, that's why `B::p` is `int*` and not simply `int`. – Jarod42 Jun 04 '15 at 09:10
  • @T.C. I made an edit, now this code gives Segmentation Fault. – piggs_boson Jun 04 '15 at 09:14
  • 1
    Generally speaking, the need to do this is a sign of bad class design ; see if you can redesign your class hierarchy so that the base does not have to actually modify data in the derived during the base construction. – M.M Jun 04 '15 at 09:48

4 Answers4

2

The way to do it is to introduce an other struct:

class A {
  public:
    int y;
    A(int &x) {
        x = 2;
        y = 1;
    }
};

struct C
{
    explicit C(int* p) p(p) {}
    int* p;
}

class B : private C, public A {
  public:
    B(int t) : C(new int), A(*p) {}
    ~B() {delete p;}
    B(const B&) = delete;
    B& operator =(const B&) = delete;
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
1

i think it's impossiable, cause p has not be assigned before call B(). it will not be assgined in the initialize-list before you call the constructor.

B() : p(new int(10) )  // p is still a junk value here
{
   // p already has a valid value here
}
IllIdan
  • 49
  • 3
  • 1
    I'm not sure what this is supposed to mean, `p` is not a junk value after `p(new int(10))` executes – M.M Jun 04 '15 at 09:47
  • p(new int(10) it's just an init-value but not be assgned before you go in the constructor – IllIdan Jun 04 '15 at 11:00
  • It's assigned as soon as `p(new int(10))` executes; you could have `q(p)` after it for example – M.M Jun 04 '15 at 11:07
1

No, you can't. The order is well defined as:

  • First, the most derived class's constructor calls the constructors of the virtual base class subobjects. Virtual base classes are initialized in depth-first, left-toright order.
  • Next, direct base class subobjects are constructed in the order they are declared in the class definition.
  • Next, (nonstatic) member subobjects are constructed in the order they were declared in the class definition.
  • Finally, the body of the constructor is executed.

If you find you're in a certain condition that have to do such weird thing, it's time to review the design again.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
-1

I tried it in another way. I don't know if it meets your requirement or not or even if its correct or not. But have a look.

class A
{
public:
  int y;
  A() {}
  A(int &x)
  {
    x = 2;
    y = 1;
  }
};

class B : public A
{
public:
  int *p;
  B(int x)  
  {
    p = new int();
    A::A(*p);
  }
};

int _tmain(int argc, _TCHAR* argv[])
{
  B b(2);
  return 0;
}

Hope its correct and helps.

Note:- to me its looks impossible to pass an initialized pointer in base initialization list.

Telokis
  • 3,399
  • 14
  • 36
Spanky
  • 1,070
  • 6
  • 11
  • `A::A(*p);` is not correct. I think it's actually illegal, but even if you meant `A(*p);`, this creates a temporary object and destroys it right away. The base class objects are all constructed before the body of the constructor is entered. – M.M Jun 04 '15 at 09:44
  • @MattMcNabb: The A::A(*p) is not illegal. The above code runs properly in Visual studio. The call will be interpreted by the compiler as a special call to base class constructor and will compile and run. Also since I am allocating on heap, it cannot be destroyed by calling delete explicitly. If you go through the code you will see I have added a default constructor which build the body. request you to check properly before your vote down. Please run the code in your system. – Spanky Jun 04 '15 at 09:54
  • I did and get `error: cannot call constructor 'B::A' directly` . I trust gcc over VS. To get a correct answer someone will have to read the C++ standard – M.M Jun 04 '15 at 09:58
  • The following link does talk about it. [link]http://stackoverflow.com/questions/21395395/calling-a-constructor-of-the-base-class-from-a-subclass-constructor-body/21395443?noredirect=1#21395443 It is possible to call base class constructor from derived class. It will result in creation of another object but its legal. I have seen many weird issues with gcc and so I trust VS a little more. – Spanky Jun 04 '15 at 10:05
  • That code talks about `Person(2)`, not `Person::Person(2)` – M.M Jun 04 '15 at 10:10
  • Anyway `A::A(*p);` is useless for `B` as creating a temporary won't initialize the base class of `B`. – Jarod42 Jun 04 '15 at 13:10