我是C++的新手,想玩转类。

我的密码

在我的世界中,有英雄和剑。英雄们持剑。这不应该太难。

// 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;
}

编译器对此有何看法

当我编译此代码(g++ hero.cpp)时,出现错误:
 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

我认为问题是

使用clang++编译代码也将失败,但是错误消息并不那么明确,因此我不会在此处发布。

似乎调用构造函数Sword(meters)失败,因为我提供了0而不是1参数。但是我显然给了它一个参数(meters),所以我想我在这里误解了一些东西。

我的错误是什么,我该怎么办?

最佳答案

您的Hero始终具有Sword

这意味着在实例化该类的那一刻,在Hero::Hero构造函数开始运行之前,它已经必须具有“默认” Sword。编译器提示它不知道如何制作这样的“默认” Sword

现在,您可以通过多种方式解决此问题:

使用初始化列表

在构造函数的定义中,您可以指定如何初始化对象的成员(在实际构造函数运行之前)。这不同于在构造函数的主体中为其分配新值(在您的示例中发生)。为此,请在构造函数的签名后指定一个冒号(:),然后在成员字段初始化程序中指定它,如下所示:

Hero() : magic_sword(2)
{
  // do other stuff to set up your hero
}

这将导致立即使用magic_sword构造函数初始化Sword::Sword(int),这意味着您不需要默认的Sword::Sword()构造函数。

阅读更多:Understanding Initialization Lists in C++

使用指针

您是否真的希望Sword完全属于Hero?您的Hero是否可以删除Sword,而另一个Hero可以接收它呢?

在这种情况下,您可能不希望Hero成为成员的Sword-相反,您想要一个指向他当前持有的Sword的指针-如果他不持有,则可能是nullptr一把剑!

08-17 05:20