I am new to C++ and want to play around with classes.
In my world there are heros and swords. Heros carry swords. This shouldn't be too hard.
// Defining swords
class Sword
{
// The most important thing about a sword is its length.
int lenght;
public:
// only constructor and destructor
Sword(int swordlength){
lenght = swordlength;
};
~Sword(){};
};
// defining heros (as people with magic swords)
class Hero
{
Sword magic_sword;
public:
// each hero gets a standard sword
Hero(){
int meters = 2;
magic_sword = Sword(meters);
};
~Hero(){};
};
int main(){
return 0;
}
When I compile this code (g++ hero.cpp
) I get an error:
In constructor 'Hero::Hero()':
20:9: error: no matching function for call to 'Sword::Sword()'
20:9: note: candidates are:
8:3: note: Sword::Sword(int)
8:3: note: candidate expects 1 argument, 0 provided
2:7: note: constexpr Sword::Sword(const Sword&)
2:7: note: candidate expects 1 argument, 0 provided
Compiling the code with clang++
also fails, but the error message is not as explicit, so I won't post it here.
It seems that calling the constructor Sword(meters)
failed because I provided 0 instead of 1 argument. But I clearly gave it an argument (meters
), so I guess I am missunderstanding something here.
What is my mistake and what can I do about it?
Your Hero
always has a Sword
.
That means that, the moment the class is instantiated, before the Hero::Hero
constructor starts running, it already has to have a "default" Sword
. The compiler is complaining that it doesn't know how to make such a "default" Sword
.
Now, there's multiple ways you can address this:
In the definition of a constructor, you can specify how your object's members should be initialized (before the actual constructor runs). This is different from assigning them a new value in the constructor's body (which happens in your example). To do this, specify a colon (:
) after the constructor's signature followed by the member field initializers, like this:
Hero() : magic_sword(2)
{
// do other stuff to set up your hero
}
This will cause the magic_sword
to be initialized using the Sword::Sword(int)
constructor right away, which means you don't need to have a default Sword::Sword()
constructor.
Read more: Understanding Initialization Lists in C++
Do you really want your Sword
to belong exclusively to your Hero
? Can your Hero
maybe drop a Sword
, and another Hero
picks it up?
In this case, you probably don't want your Hero
to have a Sword
as a member - instead, you'd want a pointer to a Sword
that he's currently holding - which can then maybe be nullptr
if he's, for example, not holding a sword!
Your Sword
class does not have a constructor with no parameters. At the beginning of Hero()
(before the opening {
), the members that are not specified in the initializer list get default constructed.
Try this:
Hero() : magic_sword(2) {
};
Or you can add another constructor to Sword
that takes no parameters.
Sword(){
lenght = -1;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With