I’m trying to instantiate a class within a class, so that the outer class contains the inner class.
This is my code:
#include <iostream>
#include <string>
class Inner {
private:
std::string message;
public:
Inner(std::string m);
void print() const;
};
Inner::Inner(std::string m) {
message = m;
}
void Inner::print() const {
std::cout << message << std::endl;
std::cout << message << std::endl;
}
class Outer {
private:
std::string message;
Inner in;
public:
Outer(std::string m);
void print() const;
};
Outer::Outer(std::string m) {
message = m;
}
void Outer::print() const {
std::cout << message << std::endl;
}
int main() {
Outer out("Hello world.");
out.print();
return 0;
}
“Inner in”, is my attempt at containing the inner within the outer, however, when I compile, i get an error that there is no matching function for call to Inner::Inner().
What have I done wrong?
Thanks.
You need to use initialization lists to initialize class members:
(Note that I passed the strings per
constreference, which is better than passing them by value. See this answer for how to pass function arguments.)This way you can specify exactly which constructors should be called for class members.
If you don’t specify a constructor, the default one will be called implicitly. Assigning to the object later will then invoke the assignment operator and override whatever the default constructor initialized the object to. That’s wasting performance at best.
Since our
Innerdoesn’t have a default constructor (declaring any constructor prevents the compiler from defining a default constructor by itself), it cannot be called, so you need to specify the constructor taking a string explicitly.Edit: Note that, if you have more than one class member, they are all initialized that way, separated by commas:
Note that the order of initialization of class members is determined by their declaration order within the class definition, not by the order they appear in the initialization list. It’s best to not to rely on initialization order, since changing that in the class definition would then create a very subtle bug in the constructor’s definition. If you can’t avoid that, put a comment besides the class members declaration:
Base class constructors are specified the same way, and they are initialized before class members, also in order of declaration in the base class list. Virtual base classes, however, are initialized before all non-virtual base classes.
Destructors, BTW, are always called in the reverse order of constructors. You can rely on that.