Candidate expects 1 argument in constructor, 0 provided

This is the code:

class cat { private: int height; public: cat (int inputHeight); }; cat::cat (int inputHeight) { height = inputHeight; } class twoCats { private: cat firstCat; cat secondCat; public: twoCats (cat theFirstCat); void addSecondCat (cat theSecondCat); }; twoCats::twoCats (cat theFirstCat) { firstCat = theFirstCat; } void twoCats::addSecondCat (cat theSecondCat) { secondCat = theSecondCat; } int main() {return 0;} 

And these are the errors:

 main.cpp: In constructor 'twoCats::twoCats(cat)': main.cpp:24:34: error: no matching function for call to 'cat::cat()' main.cpp:24:34: note: candidates are: main.cpp:9:1: note: cat::cat(int) main.cpp:9:1: note: candidate expects 1 argument, 0 provided main.cpp:1:7: note: cat::cat(const cat&) main.cpp:1:7: note: candidate expects 1 argument, 0 provided main.cpp:24:34: error: no matching function for call to 'cat::cat()' main.cpp:24:34: note: candidates are: main.cpp:9:1: note: cat::cat(int) main.cpp:9:1: note: candidate expects 1 argument, 0 provided main.cpp:1:7: note: cat::cat(const cat&) main.cpp:1:7: note: candidate expects 1 argument, 0 provided 

I do not understand the following:

  • Why is the constructor for twoCats trying to call the default constructor for cat ? Of course, he does not need to create a cat instance, how when initializing twoCats will he be given an already initialized cat instance, which will be passed by the int height argument?
  • Why is the same block of error messages displayed twice? I called g++ main.cpp on Ubuntu 12.04.
+6
source share
4 answers

In the constructor constructor constructor constructor, the constructor constructor default constructor requires a default constructor or initialize cat objects to avoid creating a default.

Why is the constructor for twoCats trying to call the default constructor for a cat? Of course, he does not need to create a cat instance, as when two Cats are initialized, will he be passed an already initialized cat instance, which will be passed an int height argument?

He needs to build default values ​​for cat objects

 private: cat firstCat; cat secondCat; 

in the twoCats class because you did not initialize them. In your constructor

 cat::cat (int inputHeight) { height = inputHeight; ^^^^^^^^^^^^^^^^^^^^ } // this is assignment 

this assignment to already created objects.

The rule is as follows: if you do not initialize the instances explicitly in the ctor initialization ctor , then

  • By default, ctor is called
  • Ultimately, you assign the already built default objects in the ctor tag.

Thus, you will be punished for additional calls if you are not initialized in the initialization list.

C ++ Standard n3337 Β§ 12.6.2 / 10 Initialization of bases and members

In the non-delegated constructor, initialization continues in the following order:

- Firstly, and only for the constructor of the derived class itself (1.8), the virtual base classes are initialized in the order they appear on the depths of the first left-right directed acyclic graph base classes, where "from left to right" is the order in which base classes appear in the base -specifier of the derived class.

- Then direct base classes are initialized in the order of declaration as they appear in the list-specifier-base (regardless of the order of the MEM-initializers).

- Then non-static data elements are initialized in the order in which they were declared in the class definition (again, regardless of the order of the MEM initializers).

- Finally, the compound operator of the constructor body is executed .

[Note: the declaration order is authorized to ensure that the base and subobject member are destroyed in the reverse order of initialization. - final note]

Here is a demo of the code.

+4
source

I would initialize the twoCats class as follows:

 class twoCats { private: cat firstCat; cat secondCat; public: twoCats (const cat& theFirstCat, const cat& theSecondCat) : firstCat (theFirstCat), secondCat (theSecondCat) { } 

};

The important part here is the colon after the constructor : It runs a member initialization list, which is the place where, if possible, all members of the data class should be initialized.

Initialization of data elements is a rather difficult problem in C ++, I suggest you google.

In particular, since you have two members of the class type, the compiler, in spite of everything, tries to initialize them in your constructor. This is done for each cat, which is probably the reason that you get a block of error messages twice. By default, the compiler tries to initialize the cat data elements using the default constructor, i.e. One without arguments. Unfortunately, cat does not have a default constructor, since you declared one with one argument. In other words, each cat must be initialized with a single argument (either copied or moved to C ++ 11).

I do not recommend declaring an additional cat constructor without arguments: it seems that there is no "default height" for cat, and -1 suggested by another answer is very strange: this does not seem to create a valid object, and you will need to check this value against by default before using any of the cat member functions.

EDIT: This is in terms of format. Regarding the semantics of your program, it may be wrong to copy cats. Maybe you need a link (or a pointer) to the objects that you initialized with your two Cats, maybe not.

+2
source

Both instances of cats must be initialized at the time they start.

To avoid this, you can defer the creation of each instance when you need it.

An easy and safe way to do this is to use std::vector to store instances.

 class cat { private: int height; public: cat (int inputHeight); }; cat::cat (int inputHeight) { height = inputHeight; } #include <vector> #include <utility> class twoCats { private: std::vector<cat> cats_; public: twoCats (cat theFirstCat) { cats_.push_back( std::move( theFirstCat ) ); } void addSecondCat (cat theSecondCat) { cats_.push_back( std::move( theSecondCat ) ); } }; int main() {return 0;} 

Alternatively, you can use boost::optional .

Or distribute the instances dynamically (use a control pointer like unique_ptr to control the lifetime).

Or, let cats be constructive by default.


As noted in thang's text, the original design does not guarantee that there are two cats in twoCats . He can have only one cat, or three or more cats. Therefore, it would be nice to change the design .

For example, you have a constructor that takes two arguments cat or cat height.

Or for another example, changing the name of twoCats .

+1
source

Like the name of your class (two categories), it always represents two cats. These kittens may be alive, dead, or even not yet born. But these will be two of them.

Your design is wrong in the sense that:

  • cat must be able to represent the unborn cat (therefore, it must have a default public constructor that sets the object to its parent state initially) or
  • your twoCats constructor should accept exactly two cats at the very beginning.
0
source

Source: https://habr.com/ru/post/975934/


All Articles