【问题标题】:C++ no matching function for call to errorC++没有匹配函数调用错误
【发布时间】:2016-01-18 11:56:57
【问题描述】:

我正在尝试模拟某个游戏作为练习(不要问我哪个,您会知道您是否知道游戏),但是,我只是在互联网上学习了对象和类,整个事情仍然如此混乱我。以下是我的代码的一部分,它给了我一个错误。

我的错误是:

C:\Users\N\Desktop\Untitled1.cpp    In constructor 'ekop::Moveset::Moveset()':
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidates are:
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 1 argument, 0 provided
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidates are:
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 1 argument, 0 provided
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidates are:
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 1 argument, 0 provided
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidates are:
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:\Users\N\Desktop\Untitled1.cpp    [Note] candidate expects 1 argument, 0 provided
C:\Users\N\Desktop\Untitled1.cpp    In constructor 'ekop::ekop()':
52  12  C:\Users\N\Desktop\Untitled1.cpp    [Note] synthesized method 'ekop::Moveset::Moveset()' first required here

我不知道出了什么问题,代码如下。 不要告诉我不要使用using namespace std;,我知道我不应该这样做,但我不会在这个程序中解决这个问题。

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cmath>
#include <string>
#include <stdio.h> /* printf, scanf, puts, NULL */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
using namespace std;

class Move
{
    public:
        Move(string a, int b, int c, int d)
        {
            name = a;
            type_num = b;
            power = c;
            accuracy = d;
        }

        void setName (string a)
        {
            name = a;
        }

        void setType_num(int a)
        {
            type_num = a;
        }

        void setPower(int a)
        {
            power = a;
        }

        void setAccuracy(int a)
        {
            accuracy = a;
        }

    private:
        string name, type;
        int type_num, power, accuracy;
};

class ekop
{
    public:
        ekop()
        {
            Moveset moveset;
        }

    private:
        class Moveset
        {
            public:
                //constructor
                //retrievors
            private:
                Move slot1, slot2, slot3, slot4;
        };
};

int main()
{
    //lines of code
    return EXIT_SUCCESS;
}

编辑1:我有这个Moveset类的构造函数,但是因为我取出它的时候并没有影响错误,所以我没有在刚才的帖子中包含它。

Moveset()
                {
                    slot1.setName("MOVE 1");
                    slot1.setType_num(rand()%18);
                    slot1.setPower(10*(rand%15+1));
                    slot1.setAccuracy(5*(rand%11+10));
                    //repeat for the rest of the slots
                }

编辑 2: 现在,如果我这样做:

        //No change before this
        class Moveset
        {
            public:
                //constructor
                //retrievors
            private:
                Move slot1("MOVE 1", rand() % 18, 10*(rand % 15 + 1), 5 * (rand % 11 + 10)),
                     slot2("MOVE 2", rand() % 18, 10*(rand % 15 + 1), 5 * (rand % 11 + 10)), 
                     slot3("MOVE 3", rand() % 18, 10*(rand % 15 + 1), 5 * (rand % 11 + 10)),
                     slot4("MOVE 4", rand() % 18, 10*(rand % 15 + 1), 5 * (rand % 11 + 10));
        };
};

//no change after this

我得到了这个错误:

62  16  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected identifier before string constant
62  16  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected ',' or '...' before string constant
63  16  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected identifier before string constant
63  16  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected ',' or '...' before string constant
64  13  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected identifier before string constant
64  13  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected ',' or '...' before string constant
65  13  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected identifier before string constant
65  13  C:\Users\N\Desktop\Untitled1.cpp    [Error] expected ',' or '...' before string constant

【问题讨论】:

    标签: c++ class object c++11


    【解决方案1】:

    MoveSet 包含四个默认初始化的 Move 实例,但 Move 没有默认构造函数 - 因为您定义了一个构造函数,它禁止自动生成默认构造函数。

    由于该类需要用户定义的默认构造函数(内置类型数据成员将具有任意值),因此定义一个。

    定义它的一种方法是为现有构造函数的所有参数提供默认值,但我会定义一个单独的默认构造函数。


    顺便说一句,现有的代码

    Move(string a, int b, int c, int d)
    {
        name = a;
        type_num = b;
        power = c;
        accuracy = d;
    }
    

    ... 使用赋值来初始化成员,作为执行此操作的一般方法存在问题。也就是说,不能默认初始化的类类型的成员不能以这种方式初始化。您会遇到与上述相同的问题,即有关缺少默认构造函数的错误消息。

    一种解决方案是使用成员初始化列表,如下所示:

    Move( string a, int b, int c, int d )
        : name( a ), type_num( b ), power( c ), accuracy( d )
    {}
    

    还有更多可能的改进,例如move 用于提高效率或const 用于清晰(不幸的是必须在它们之间进行选择),但重要的是通常采用这种使用成员初始化器列表的约定,这比分配给成员的工作更普遍。

    【讨论】:

    • 很抱歉有许多编辑纠正了愚蠢的事情,我刚起床,决定在喝一杯最重要的咖啡之前回答这个问题。
    • 这是一个更好的答案。我实际上并不知道定义非默认构造函数会抑制默认构造函数的自动生成:)
    • 我仍然很困惑......问题是我不确定是什么让我感到困惑,但我会尝试问......这是否意味着因为我为 Move 定义了一个构造函数,但是当我在 Moveset 下创建了一个 Move 对象我没有输入参数?
    • @nayfaan:是的,这是解决问题的另一种方法,为Moveset 构造函数中的每个Move 对象成员提供参数。
    • @Cheersandhth.-Alf 我在帖子的第二次编辑中这样做了,但又返回了另一个错误?
    【解决方案2】:

    基本上,Move 没有默认构造函数。要使此代码正常工作,请将以下内容添加到 Move 类的公共部分:

    Move() {
        //Give fields default values here
    }
    

    当你声明一个变量而不初始化它时,它会调用默认构造函数(没有参数的构造函数)给变量默认值,直到它被使用。有时会保留这些默认值,有时您会为其分配一个新对象。但这取决于您想要做什么,并不真正相关。

    编辑:好的,详细说明一下,有几种方法可以在 C++ 中声明/初始化变量。我将使用 std::string 作为示例,但这适用于任何类型(即使是基本类型,尽管它们的类本身没有定义,就像语言中内置的一样):

    std::string str1;
    std::string str2 = "Two";
    std::string str3("Three");
    std::string str4 = std::string("Four");
    

    str1只是一个声明,其余的都是声明初始化(他们声明变量,然后给它一个初始值)。

    str1 调用默认构造函数,因为没有提供初始值。因此,编译器需要 something 分配给str1,而默认构造函数提供了一些东西。

    str2str3 实际上是完全相同的调用的不同样式 - 调用参数化的 std::string 构造函数之一(即,在本例中为 std::string(const char*) 构造函数)。 str3 是不言自明的:它就像一个普通的函数调用,只是调用的是构造函数,而不是普通的函数。 str2 展示了一个关于 C++ 的有趣之处 - 当使用 = 符号初始化变量时,它会调用构造函数。在这种情况下,它调用了一个转换构造函数,我将对此进行更详细的介绍,但我会等到最后。

    最后,str4 与其他人不同,实际上调用了 两个 构造函数(从技术上讲,它是效率最低的)。第一个调用的是std::string("Four"),它创建了一个未命名的std::string 对象,然后传递给std::string复制构造函数(看起来像@987654337 @) 来创建str4 变量。

    它是这样的:一个未命名的std::string 对象被创建并被赋予值“四”(std::string("Four"))。然后将该对象传递(再次通过那个古怪的= 符号)到​​std::string 复制构造函数,以将未命名的字符串对象复制到str4,完成它的创建。看到这个方法调用了两个构造函数,创建了一个额外的不必要的对象,用于创建str4

    现在 - 转换构造函数。如果一个类定义了一个带有单个参数的构造函数,那么该构造函数就是一个转换构造函数。所以基本上,每当该类的对象被初始化为一个可以被转换构造函数获取的值时,该值就会被传递给构造函数,并且构造函数从那里处理它。

    转换构造函数没有什么特别的——它们只是普通的构造函数。唯一的区别是初始化时不需要括号来调用它,只需将值放在那里即可。使用std::string(const char*) 构造函数。此构造函数用于将 const char*(在 C 语言时代称为 C 样式字符串)转换为 std::string 对象。使用转换构造函数,您可以将参数值(例如 const char*)放在需要 std::string 的任何位置(例如,在函数的返回值中),它会自动从 @ 创建一个 std::string 对象987654350@(如果你不知道,每当你输入类似"Hello World" 的东西时,它实际上是一个const char* 值,尽管它经常被你的代码转换为std::string)。

    在仍然有一个参数的情况下避免创建转换构造函数的一种方法(因为自动 - 也就是隐式 - 转换有时会很烦人)是将关键字 explicit 放在构造函数声明的前面,这将告诉编译不要进行隐式转换——这意味着无论何时要转换,都必须使用std::string("Hello World") 而不仅仅是"Hello World"

    希望你明白我在说什么,如果不是让我知道的话!顺便说一句,我仍然需要验证我所说的关于 = 标志的内容,我将在回家时使用 Visual Studio 调试器来执行此操作。我将更新帖子以反映我的发现。

    【讨论】:

    • 我有一个构造函数,但我没有在这篇文章中包含它。我将更新帖子以包含它。我没有包含它的原因是因为在我取出它之后它仍然给了我同样的错误所以我认为它与我现在面临的问题无关
    • 我实际上是在谈论一个 default 构造函数,它在这个实例中是必需的。你有其中之一吗?
    • 什么是默认构造函数?对不起,我是新手
    • @nayfaan 很好,每个人都会经历这个哈哈 :) 默认构造函数是没有参数的构造函数。这仅在声明变量(或类的属性)时使用。我会在我的回答中为您添加更多详细信息。干杯的回答很好地解释了事情。
    • 我明白了,如果我有一个默认构造函数和另一个带参数的构造函数,当我在没有参数的情况下初始化时,它使用默认构造函数,但如果我给它参数,它会得到默认构造函数吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多