Reputation: 21518
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
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
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
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
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
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