简体   繁体   中英

C++ no matching function for call to error

I am trying to simulate a certain game as an exercise (dont ask me which, you will know if you know the game), however, I just learnt objects and class on the internet and the whole thing is still so confusing to me. The following is a section of my code that is giving me an error.

The error I have is:

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

I don't know what went wrong, the code is below. Don't tell me not to use using namespace std; , I know I am not supposed to do that but I am not going to fix that in this program.

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

edit 1: I had this constructor for the class Moveset, but since it didnt affect the error when I took it out, so I didnt include that in the post just now.

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
                }

edit 2: Now if I do this instead:

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

I get this error instead:

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

A MoveSet contains four default-initialized Move instances, but Move has no default constructor – because you have defined a constructor, which suppresses automatic generation of a default constructor.

Since the class needs a user-defined default constructor (built in type data members will otherwise have arbitrary values), define one.

One way to define it is to provide default values for all arguments of the existing constructor, but I'd define a separate default constructor.


In passing, the existing code

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

… which uses assignments to initialize members, has a problem as a general way to do this. Namely, that members of class type that can't be default-initialized, can't be initialized this way. You'd experience the same problem as above, namely error messages about lacking a default constructor.

A solution is to use a member initializer list , like this:

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

There are further possible refinements, such as move for efficiency or const for clarity (unfortunately one has to choose between them), but the important thing is to just generally adopt this convention of using member initializer lists, which works much more generally than assignments to members.

Basically, you've got no default constructor for Move. To make this code work, add the following to the public section of the Move class:

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

When you declare a variable without initializing it, it calls the default constructor (the constructor with no arguments) to give the variable default values until it's used. Sometimes these default values are kept, sometimes you assign a new object to it.. But that's depends on what you want to do and isn't really relevant.

Edit: Okay so to elaborate, there are a couple of ways to declare/initialize variables in C++. I'll use std::string as an example, but this applies to any type (even the fundamental types, though their classes aren't defined, per se, as much as just built into the language):

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

str1 is just a declaration, the rest are declarations and initializations (they declare the variable, and then give it an initial value).

str1 calls the default constructor, because no initial value is provided. Therefore, the compiler needs something to assign to str1 and the default constructor provides that something.

str2 and str3 are actually different styles of the exact same call - a call to one of the parameterized std::string constructors (namely, in this case, the std::string(const char*) constructor). str3 is fairly self explanatory: its like a normal function call, only it's the constructor being called, not a normal function. str2 shows a funny thing about C++ - when initializing a variable with the = sign, it calls a constructor. In this case, is calls a converting constructor , which I'll go into a little more detail about, but I'll wait till the end.

Finally, str4 , unlike the others, actually calls two constructors (making it the least efficient, technically speaking). The first one called is the std::string("Four") , which creates an unnamed std::string object, which is then passed to the std::string copy constructor (which looks like std::string(std::string&) ) to create the str4 variable.

It goes like this: an unnamed std::string object is created and given the value "Four" ( std::string("Four") ). That object is then passed (by that quirky = sign again) to the std::string copy constructor, to copy the unnamed string object to str4 , completing it's creation. See that this method calls two constructors, creating an extra unnecessary object that's used in the creation of str4 .

Now - converting constructors . If a class defines a constructor that takes a single parameter, that constructor is a converting constructor. So basically, whenever an object of that class is initialized with a value that can be taken by a converting constructor, that value is passed to the constructor and the constructor handles it from there.

Converting constructors aren't anything special - they're just normal constructors. The only difference is that you don't need parentheses to call it when initializing, you just put the value there. Take the std::string(const char*) constructor. This constructor acts to convert const char* (known as a C-style string, from the days of the C language) to a std::string object. With a converting constructor, you can put the parameter value (eg const char*) anywhere that a std::string is required (in the return value of a function, for example) and it will automatically create a std::string object from the const char* (in case you didn't know, whenever you type something like "Hello World" it is actually a const char* value, though is it often converted to a std::string by your code).

One way you can avoid creating a converting constructor while still having one argument (because automatic - aka implicit - conversions can sometimes be annoying) is to put the keyword explicit in front of the constructor declaration, which will tell the compilation not to do implicit conversions - meaning that whenever you want to convert, you must use std::string("Hello World") rather than just "Hello World" .

Hopefully you understand that I'm talking about, if not just let me know! By the way, I still need to verify what I've said about that = sign, which I'll use the Visual Studio debugger to do when I get home. I will update the post to reflect my findings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM