【问题标题】:Default constructor missing - but I'm not calling it?缺少默认构造函数 - 但我没有调用它?
【发布时间】:2019-07-21 10:43:46
【问题描述】:

我正在编写一个 C++ 应用程序,其中有一个带有两个嵌套结构的 Controller 类,在我的头文件中定义如下:

class Controller {
    struct help_message {   // controller.hpp, line 19
        std::string summary;
        std::string details;
        help_message(const std::string&, const std::string&);
    };

    struct player_command {
        cmd_t cmd;
        help_message help;
        // cmd_t is my own typedef, irrelevant for this question
        player_command(const cmd_t&, const help_message&);
    };

    // more members...
};

在我的源文件中,我有这个:

Controller::player_command::player_command(const Controller::cmd_t& c, const help_message& h) {
    cmd = c;
    help = h;
};

Controller::help_message::help_message(const std::string& s, const std::string& d) {
    summary = s;
    details = d;
};

我认为这很好,但是当我编译时,这是我得到的(controller.cpp 第12行是上面源代码sn-p的第一行):

g++  -g -Wall -std=c++0x  -c -o controller.o controller.cpp
controller.cpp: In constructor ‘palla::Controller::player_command::player_command(void (palla::Controller::* const&)(const args_t&), const palla::Controller::help_message&)’:
controller.cpp:12:93: error: no matching function for call to ‘palla::Controller::help_message::help_message()’
controller.cpp:12:93: note: candidates are:
In file included from controller.cpp:7:0:
controller.hpp:22:3: note: palla::Controller::help_message::help_message(const string&, const string&)
controller.hpp:22:3: note:   candidate expects 2 arguments, 0 provided
controller.hpp:19:9: note: palla::Controller::help_message::help_message(const palla::Controller::help_message&)
controller.hpp:19:9: note:   candidate expects 1 argument, 0 provided
controller.hpp:19:9: note: palla::Controller::help_message::help_message(palla::Controller::help_message&&)
controller.hpp:19:9: note:   candidate expects 1 argument, 0 provided
make: *** [controller.o] Error 1

据我推断,编译器在某处试图调用不存在的help_message 的默认构造函数。然后它尝试将调用与我创建的构造函数以及生成的复制构造函数和赋值运算符匹配,并在参数数量上失败。

但是我的代码的哪一部分调用了默认构造函数?我该如何解决这个错误?

【问题讨论】:

  • 已经回答得很好,但换一种说法:每个构造函数首先构造所有子对象进入{}标记中的主体。如果您不说如何,它将尝试默认构造函数。所以你不妨说说如何使用 mem-initializer-list。

标签: c++ constructor rule-of-three


【解决方案1】:

player_command() 构造函数首先默认构造help,然后分配给它:

Controller::player_command::player_command(const Controller::cmd_t& c, const help_message& h) {
    cmd = c;
    help = h;
};

将其更改为:

Controller::player_command::player_command(const Controller::cmd_t& c, const help_message& h)
:  cmd(c),
   help(h)
{
};

Benefits of Initialization lists

【讨论】:

  • 微妙的错误(至少对我来说)——快速捕捉和很好的解释。赞一个!
  • 根本不是错误。初始化和赋值之间只有一个(不是那么细微的)区别。
【解决方案2】:

player_command 结构包含一个help_message(帮助),并且help_message 没有默认构造函数。当调用player_command 构造函数时,默认会默认构造帮助成员变量。您会立即为给定参数分配帮助,但这将是在默认构造之后。而是将构造函数更改为:

Controller::player_command::player_command(const Controller::cmd_t& c, const help_message& h) : cmd(c), help(h) 
{}

这将为 cmd 和 help 成员变量调用复制构造函数,而不是执行默认构造然后赋值。

【讨论】:

    【解决方案3】:

    您没有使用避免复制构造函数的语法。参数通过引用传递(无复制构造函数),但在分配给 ivar 时确实被复制。

    Class::Class(const Variable &var) {
      this->var = var; // assignment here, this invokes copy contructor!
    }
    

    您应该使用以下语法:

    Class::Class(const Variable &var) : var(var) { }
    

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 2023-03-20
      • 2021-05-27
      • 1970-01-01
      • 2011-04-27
      相关资源
      最近更新 更多