Baruch
Baruch

Reputation: 21518

Constructor that depends on object not yet constructed

In C++, I have an object A that has a constructor that accepts an istream (to load itself from a file). I have another class that has an A as a member. I can't call A's constructor from the initialization list because I didn't open the istream yet. Once I open it in the constructor of my class, it is too late to call the constructor of A. Is there some way to open an istream in the initialization list into some temporary object so that I can send it to A's constructor?
And if there is, is there any type of guarantee on the order the initialization list is called so that the istream would get initialized before the A?

An example may help:

class A {
public:
  A(std::istream const&);
}

class B {
public:
  B(std::istream const&);
}

class MyClass {
  A a;
  B b;
public:
  MyClass() : a(is), b(is) {  // <-- How to do this?
    std::istream is("path");
  }
}

Upvotes: 2

Views: 166

Answers (5)

Eran
Eran

Reputation: 22020

Here's yet another idea... If you want to avoid dynamic allocations and use a single, temporary istream, you can move the load phase of A and B away from their constructor:

class A {
public:
  Load(std::istream const&);
}

class B {
public:
  Load(std::istream const&);
}

class MyClass {
  A a;
  B b;
public:
  MyClass() {
    std::istream is("path");
    a.Load(is);
    b.Load(is);
  }
}

This, BTW, calls for A and B inheriting the load abilities from some shared parent, but that's obviously beyond the scope of this question.

Upvotes: 2

Arne
Arne

Reputation: 2146

As both member should depend on the same istream, why not:

class A {
public:
  A(std::istream const&);
}

class B {
public:
  B(std::istream const&);
}

class MyClass {
  A a;
  B b;
public:
  MyClass(std::istream const& is) : a(is), b(is) {
  }
}

Upvotes: 2

user52875
user52875

Reputation: 3058

The initialization of the member variables of a class will happen in the order that you specify them in the class declaration.

Note that gcc will warn (given -Wall) when the order in the initializer list does not correspond to the order of declaration of the member variables. The declaration order in the class is authoritative.

class A {
public:
    A(std::istream const&);
}

class B {
public:
  B(std::istream const&);
}

class MyClass {
  std::istream is;
  A a;
  B b;
public:
  MyClass() : is("path"), a(is), b(is) {
  }
}

Upvotes: 1

Eitan T
Eitan T

Reputation: 32930

Maybe I'm missing something, but what's the problem with:

class MyClass {
    A* a;
    B* b;
public:
    MyClass() {
      std::istream is("path");
      a = new A(is);
      b = new B(is);
    }

    ~MyClass() {
        delete a;
        delete b;
    }
}

Upvotes: 1

SingerOfTheFall
SingerOfTheFall

Reputation: 29966

Use pointers to objects instead:

class MyClass {
   A *a;
   B *b;
public:
   MyClass()
   {
       std::istream is("path");
       a = new A(is);
       b = new B(is);
   }
}

Don't forget to free the memory in the destructor.

Upvotes: 2

Related Questions