The code does not compile. I do not understand what the error is, help please)
#include <iostream>
#include <fstream>
class Record{
std::string product_name;
std::string product_category;
int price;
int amount;
public:
Record(std::string newName, std::string newCategory, int newPrice, int newAmount){
product_name=newName;
product_category=newCategory;
price=newPrice;
amount=newAmount;
}
std::string getName(){
return product_name;
}
std::string getCategory(){
return product_category;
}
int getPrice(){
return price;
}
int getAmount(){
return amount;
}
void setName(std::string newName){
product_name=newName;
}
void setCategory(std::string newCategory){
product_category=newCategory;
}
void setPrice(int newPrice){
price=newPrice;
}
void setAmount(int newAmount){
amount=newAmount;
}
};
int main(){
Record r1;
r1.setName("beer");
r1.setCategory("alcohol");
r1.setPrice(12);
r1.setAmount(32);
Record r2("carrot", "vegetables", 123, 1932);
std::cout<<r1.getName()<<" "<<r1.getCategory()<<" "<<r1.getPrice()<<" "<<r1.getAmount()<< std::endl;
std::cout<<r2.getName()<<" "<<r2.getCategory()<<" "<<r2.getPrice()<<" "<<r2.getAmount()<< std::endl;
Record r3[2];
std::string a;
float b;
unsigned int c;
for(unsigned int i=0; i<2; ++i){
std::cout<<"input name: ";
std::cin>>a;
r3[i].setName(a);
std::cout<<"input category: ";
std::cin>>a;
r3[i].setCategory(a);
std::cout<<"input price: ";
std::cin>>b;
r3[i].setPrice(b);
std::cout<<"input amount: ";
std::cin>>c;
r3[i].setAmount(c);
}
for(unsigned int i=0; i<2; ++i){
std::cout<<r3[i].getName()<<" "<<r3[i].getCategory()<<" "<<r3[i].getPrice()<<" "<<r3[i].getAmount()<< std::endl;
}
return 0;
}
Error text:
g++ -Wall -c "main.cpp" ( /media/ad/4GB-NTFS/prog/laba2)
main.cpp: In function ‘int main()’:
main.cpp:46:12: error: no matching function for call to ‘Record::Record()’
Record r1;
^
main.cpp:12:1: note: candidate: Record::Record(std::__cxx11::string, std::__cxx11::string, int, int)
Record(std::string newName, std::string newCategory, int newPrice, int newAmount){
^
main.cpp:12:1: note: candidate expects 4 arguments, 0 provided
main.cpp:6:7: note: candidate: Record::Record(const Record&)
class Record{
^
main.cpp:6:7: note: candidate expects 1 argument, 0 provided
main.cpp:54:16: error: no matching function for call to ‘Record::Record()’
Record r3[2];
^
main.cpp:12:1: note: candidate: Record::Record(std::__cxx11::string, std::__cxx11::string, int, int)
Record(std::string newName, std::string newCategory, int newPrice, int newAmount){
^
main.cpp:12:1: note: candidate expects 4 arguments, 0 provided
main.cpp:6:7: note: candidate: Record::Record(const Record&)
class Record{
^
main.cpp:6:7: note: candidate expects 1 argument, 0 provided
Your class doesn't have a default constructor. So when you say:
Record r1;
the compiler doesn't know how to create the r1 object. You either need to provide all the parameters when r is created:
Record r1( "foo", "bar", 1, 2 );
or better completely rethink the design of your program.
You have overriden the constructor of your class, and so there is not one that accepts zero arguments as this requires:
Record r1;
Define a default constructor:
Record() {}
main.cpp:46:12: error: no matching function for call to ‘Record::Record()’
That is, at this point:
Record r1;
You are trying to instantiate the object r1 with a default constructor (Record::Record). Indeed you are not providing any parameter.
Moreover the compiler continues:
note: candidate expects 4 arguments, 0 provided
Following your class interface, the only way to instantiate a Record object is to use the only constructor provided, that is:
Record(std::string, std::string, int, int);
If you want to allow to instantiate an Record object with a default constructor you have to provide it.
C++11 allows you to write:
Record() = default;
In order to define a default constructor.
You have to define a constructor with no parameters.
Record r1 tries to call Record() but it doesn't find it. Just add the extra constructor in your class. It can be empty. This will also solve the same problem with Record r3[2].
P.S. (unrelated to the question, but helpful)
Looking at your code, I suggest you check out member initializer lists for implementing your constructors. Why? See here.
Related
Previous SO post consulted: Default Constructor Calls
Here is the code:
#include <iostream>
#include <unordered_map>
using namespace std;
struct item {
std::string name;
int price;
// item() = default;
item(std::string n, int p): name(n), price(p) {}
};
void createItems(std::unordered_map<std::string, item>& blah);
int main()
{
std::unordered_map<std::string, item> blah;
createItems(blah);
cout << blah["armor"].name << " " << blah["armor"].price << std::endl;
return 0;
}
void createItems(std::unordered_map<std::string, item>& blah) {
item i1{"armor", 1000};
item i2{"amulet", 200};
blah["armor"] = i1;
blah["amulet"] = i2;
return;
}
The error message when run:
main.cpp:20:25: required from here
/usr/include/c++/11/tuple:1824:9: error: no matching function for call to ‘item::item()’
1824 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:10:5: note: candidate: ‘item::item(std::string, int)’
10 | item(std::string n, int p): name(n), price(p) {}
| ^~~~
main.cpp:10:5: note: candidate expects 2 arguments, 0 provided
main.cpp:6:8: note: candidate: ‘item::item(const item&)’
6 | struct item {
| ^~~~
main.cpp:6:8: note: candidate expects 1 argument, 0 provided
main.cpp:6:8: note: candidate: ‘item::item(item&&)’
main.cpp:6:8: note: candidate expects 1 argument, 0 provided
From my understanding, the default constructor is called but since I commented the line out the call results in an error.
Question: Why (and where) is the default constructor needed? My suspicion is that blah["armor"] calls the default constructor, but why?
As tkausl hinted at in their comment, the index operator is what needs the default constructor.
What the index operator does is
find tree location for key
if this location does not exist
create location
copy-construct key there
default-construct value there
return reference to value at location
Step 5 needs the default constructor. And since everything needs to be resolved at compile time, it needs the default constructor even if you never actually use a non-existent key. (You do, though.)
If you don't have a default constructor, you can't use the index operator. Use insert, emplace or try_emplace add elements to the map, and find or at to look them up.
Let's say I have this dummy class definition:
class Node
{
public:
Node ();
Node (const int = 0);
int getVal();
private:
int val;
};
And dummy constructor implementations for educational purposes only as well:
Node::Node () : val(-1)
{
cout << "Node:: DEFAULT CONSTRUCTOR" << endl;
}
Node::Node(const int v) : val(v)
{
cout << "Node:: CONV CONSTRUCTOR val=" << v << endl;
}
Now, if I compile (with options: -Wall -Weffc++ -std=c++11) the code below:
#include <iostream>
#include "node.h"
using namespace std;
int main()
{
Node n;
return 0;
}
I get this error, and does not compile at all:
node_client.CPP: In function ‘int main()’:
node_client.CPP:10:16: error: call of overloaded ‘Node()’ is ambiguous
Node n;
^
node_client.CPP:10:16: note: candidates are:
In file included from node_client.CPP:4:0:
node.h:14:5: note: Node::Node(int)
Node (const int = 0);
^
node.h:13:2: note: Node::Node()
Node ();
^
I cannot understand why.
As far as I know (I am learning C++), a call to Node::Node() should not be ambiguous with respect to Node::Node(const int) because the have a different parameter signature.
There is something I am missing: What it is?
a call to Node::Node() should not be ambiguous with respect to Node::Node(const int) because the have a different parameter signature.
Sure that is ambiguous. Think twice!
You have
Node ();
Node (const int = 0);
which one should be selected when you call Node()?? The one with the defaulted value parameter?
It should work without providing the default:
Node ();
Node (const int); // <<<<<<<<<<<<< No default
The compiler just cannot know if you want to call the default constructor or the int constructor with a default value.
You have to remove the default value or remove the default constructor (which does the same thing as your constructor with int so that's not really a problem!)
I'm getting back into writing some C++ and I'm honestly rusty. I get the feeling I'd find a quick answer to my question if I just knew how to phrase it properly, but still I'd appreciate your help.
sanitycheck.cpp:
#include <string>
using namespace std;
typedef struct STR_1 {
int val_a, val_b;
STR_1 (int a, int b)
{ val_a = a; val_b = b; }
} STR_1;
typedef struct STR_2{
string name;
STR_1 myStr1;
STR_2 (string n, STR_1 s)
{ name=n; myStr1 = s; }
} STR_2;
int main(){
return 0;
} // end main
When I try to compile with g++ -o sanitycheck ./test/sanitycheck.cpp I get the following,
./test/sanitytest.cpp: In constructor ‘STR_2::STR_2(std::string, STR_1)’:
./test/sanitytest.cpp:25:3: error: no matching function for call to ‘STR_1::STR_1()’
{ name=name; myStr1 = &s; }
^
./test/sanitytest.cpp:25:3: note: candidates are:
./test/sanitytest.cpp:11:3: note: STR_1::STR_1(int*, int*)
STR_1 (int *a, int *b)
^
./test/sanitytest.cpp:11:3: note: candidate expects 2 arguments, 0 provided
./test/sanitytest.cpp:7:16: note: STR_1::STR_1(const STR_1&)
typedef struct STR_1 {
^
./test/sanitytest.cpp:7:16: note: candidate expects 1 argument, 0 provided
./test/sanitytest.cpp:25:23: error: no match for ‘operator=’ (operand types are ‘STR_1’ and ‘STR_1*’)
{ name=name; myStr1 = &s; }
^
./test/sanitytest.cpp:25:23: note: candidate is:
./test/sanitytest.cpp:7:16: note: STR_1& STR_1::operator=(const STR_1&)
typedef struct STR_1 {
^
./test/sanitytest.cpp:7:16: note: no known conversion for argument 1 from ‘STR_1*’ to ‘const STR_1&’
One thing I'm not clear on is why would STR_1 myStr1; of STR_2 need to call the STR_1 constructor in the first place? Couldn't I initialize both types with,
int main()
{
STR_1 bob = STR_1(5,6);
STR_2 tom = STR_2('Tom',bob);
return 0;
}
Thanks!
Unless it is not already clear from the link in the comments to the OP: this here,
typedef struct STR_2{
string name;
STR_1 myStr1;
STR_2 (string n, STR_1 s) // here the myStr1 default constructor is called
{ name=name; myStr1 = s; }
} STR_2;
requires STR_1 to be default constructible. In order to work around, you have to construct the member STR_1 myStr1; in the constructor's initializer list:
STR_2 (string n, STR_1 s) : name(n), myStr1(s) {}
DEMO
This calls the compiler generated copy-constructor of STR_1 instead of the default constructor (the automatic generation of which is suppressed by providing a custom constructor).
Another option would be to use a pointer to STR_1:
typedef struct STR_2{
string name;
std::unique_ptr<STR_1> myStr1;
STR_2 (string n, STR_1 s)
{ name=name; myStr1 = std::make_unique<STR_1>(s); } //just for the sake of explanation
//again, this would be better
//done in the initializer list
} STR_2;
Yet, I would depart from the first alternative only for a good reason.
How do I call a template constructor whith objects of another class?
Example:
#include <iostream>
using namespace std;
class RGB{
private:
int _R;
int _G;
int _B;
public:
RGB(int a, int b, int c){
_R=a;
_G=b;
_B=c;
}
};
class Gray{
int _G;
public:
Gray(int x){
_G=x;
}
};
template <class T1, class T2>
class Pixel{
public:
Pixel(T1 i, T2 j, int a, int b){
foo=i;
bar=j;
x=a;
y=b;
}
void setPixel(T1 a, T2 b){
foo=a;
bar=b;
}
void getPixel();
private:
int x;
int y;
T1 foo;
T2 bar;
};
int main(){
Gray g(3);
RGB rgb(4, 5, 6);
Pixel<Gray,RGB> pi(g, rgb, 10,27);
return 0;
}
I can use the constructor of the class only with the default constructors of the two classes Bar1 and Bar2 but not with the two objects of the classes that I have created before(in this case bar1 and bar2).
Errors are:
main.cpp: In instantiation of 'Pixel::Pixel(T1, T2, int, int) [with T1 = Gray; T2 = RGB]':
main.cpp:62:37: required from here
main.cpp:35:37: error: no matching function for call to 'Gray::Gray()'
main.cpp:35:37: note: candidates are:
main.cpp:26:5: note: Gray::Gray(int)
main.cpp:26:5: note: candidate expects 1 argument, 0 provided
main.cpp:23:7: note: Gray::Gray(const Gray&)
main.cpp:23:7: note: candidate expects 1 argument, 0 provided
main.cpp:35:37: error: no matching function for call to 'RGB::RGB()'
main.cpp:35:37: note: candidates are:
main.cpp:16:9: note: RGB::RGB(int, int, int)
main.cpp:16:9: note: candidate expects 3 arguments, 0 provided
main.cpp:9:7: note: RGB::RGB(const RGB&)
main.cpp:9:7: note: candidate expects 1 argument, 0 provided
The errors go away if I add default values to the RGB and Gray constructors.
Sorry for the mess, I'm new here...
You need to learn about initialization lists:
Pixel(T1 i, T2 j, int a, int b) : x(a), y(b), foo(i), bar(j) {
}
foo=i;, etc. in the body of the Pixel constructor is assigning to an already existing object. When your Pixel constructor is called, it trys to call the default constructor for its subobjects, Gray and RGB, however, both those types do not have default constructors generated since you provide a user-defined constructor. The solution is to use initialization lists to initialize the subobjects in your Pixel class.
Also, note that subobjects of the class are constructed in the order they are declared inside the class definition, so you should always initialize them in the same order as they are declared in your constructor initialization list.
class Sample
{
public:
Sample();
Sample(int i);
Sample(Sample& s);
~Sample();
};
Sample::Sample()
{
cout<<"Default constructor called\n";
}
Sample::Sample(int i)
{
cout<<"1-argument constructor called\n";
}
Sample::Sample(Sample& s)
{
cout<<"Copy constructor called\n";
}
Sample::~Sample()
{
cout<<"Destructor called\n";
}
void Fun(Sample s)
{
}
int main()
{
Sample s1;
Fun(5);
return 0;
}
I expected an implicit conversion of 5.
But, When I compile the above code, I get following error:
main.cpp:7:8: error: no matching function for call to ‘Sample::Sample(Sample)’
main.cpp:7:8: note: candidates are:
Sample.h:10:3: note: Sample::Sample(Sample&)
Sample.h:10:3: note: no known conversion for argument 1 from ‘Sample’ to ‘Sample&’
Sample.h:9:3: note: Sample::Sample(int)
Sample.h:9:3: note: no known conversion for argument 1 from ‘Sample’ to ‘int’
Sample.h:8:3: note: Sample::Sample()
Sample.h:8:3: note: candidate expects 0 arguments, 1 provided
Helper.h:6:13: error: initializing argument 1 of ‘void Fun(Sample)’
What is the problem? When i remove the copy constructor, the above code compiles successfully.
Thanks in advance.
Temporaries cannot bind to non-const references. Your copy constructor should be:
Sample::Sample(const Sample&)
Removing it tells the compiler to generate a trivial one, which will have the above signature.