c++中没有对错误调用的匹配函数

C++ no matching function for call to error

本文关键字:函数 调用 错误 c++      更新时间:2023-10-16

我试着模拟一个特定的游戏作为练习(不要问我哪一个,你会知道如果你知道这个游戏),然而,我只是在网上学习对象和类,整个事情对我来说仍然很困惑。下面是我的一段代码,它给了我一个错误。

我得到的错误是:

C:UsersNDesktopUntitled1.cpp    In constructor 'ekop::Moveset::Moveset()':
56  9   C:UsersNDesktopUntitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:UsersNDesktopUntitled1.cpp    [Note] candidates are:
14  3   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 1 argument, 0 provided
56  9   C:UsersNDesktopUntitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:UsersNDesktopUntitled1.cpp    [Note] candidates are:
14  3   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 1 argument, 0 provided
56  9   C:UsersNDesktopUntitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:UsersNDesktopUntitled1.cpp    [Note] candidates are:
14  3   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 1 argument, 0 provided
56  9   C:UsersNDesktopUntitled1.cpp    [Error] no matching function for call to 'Move::Move()'
56  9   C:UsersNDesktopUntitled1.cpp    [Note] candidates are:
14  3   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(std::string, int, int, int)
14  3   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 4 arguments, 0 provided
11  7   C:UsersNDesktopUntitled1.cpp    [Note] Move::Move(const Move&)
11  7   C:UsersNDesktopUntitled1.cpp    [Note] candidate expects 1 argument, 0 provided
C:UsersNDesktopUntitled1.cpp    In constructor 'ekop::ekop()':
52  12  C:UsersNDesktopUntitled1.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:UsersNDesktopUntitled1.cpp    [Error] expected identifier before string constant
62  16  C:UsersNDesktopUntitled1.cpp    [Error] expected ',' or '...' before string constant
63  16  C:UsersNDesktopUntitled1.cpp    [Error] expected identifier before string constant
63  16  C:UsersNDesktopUntitled1.cpp    [Error] expected ',' or '...' before string constant
64  13  C:UsersNDesktopUntitled1.cpp    [Error] expected identifier before string constant
64  13  C:UsersNDesktopUntitled1.cpp    [Error] expected ',' or '...' before string constant
65  13  C:UsersNDesktopUntitled1.cpp    [Error] expected identifier before string constant
65  13  C:UsersNDesktopUntitled1.cpp    [Error] expected ',' or '...' before string constant

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没有默认构造函数。要使此代码工作,请将以下内容添加到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调用默认构造函数,因为没有提供初始值。因此,编译器需要一些东西来赋值给str1,而默认构造函数提供了这些东西。

str2str3实际上是完全相同调用的不同样式——调用参数化的std::string构造函数之一(即,在本例中,std::string(const char*)构造函数)。str3是相当不言自明的:它就像一个普通的函数调用,只是它是被调用的构造函数,而不是一个普通的函数。str2显示了c++中一件有趣的事情——当初始化带有=符号的变量时,它调用构造函数。在本例中,它调用一个转换构造函数,我将对此进行更详细的讨论,但我将等到最后。

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

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

Now - 转换构造函数。如果类定义了接受单个形参的构造函数,则该构造函数是转换构造函数。因此,基本上,每当该类的对象初始化为可由转换构造函数获取的值时,该值将传递给构造函数,并由构造函数从那里处理它。

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

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

希望你明白我在说什么,如果不只是让我知道!顺便说一下,我仍然需要验证我所说的关于=标志的内容,当我回家时,我将使用Visual Studio调试器来做。我将更新这篇文章来反映我的发现。