Compiler not recognizing the constructor, expects arguments and recognizes zero - c++

I am trying to organize data into a binary tree and have created a struct to better organize the data. However, my compiler has this error message every time I try to run my code:
BinaryTree.cpp:41:37: error: no matching function for call to 'person::person()'
node (person i, node * l, node * r){
^
BinaryTree.cpp:14:2: note: candidate: 'person::person(int, int, std::__cxx11::string, std::__cxx11::string, int)'
person(int ss, int bd, string fn, string ln, int zc) {
^~~~~~
BinaryTree.cpp:14:2: note: candidate expects 5 arguments, 0 provided
BinaryTree.cpp:10:8: note: candidate: 'person::person(const person&)'
struct person {
^~~~~~
BinaryTree.cpp:10:8: note: candidate expects 1 argument, 0 provided
BinaryTree.cpp:10:8: note: candidate: 'person::person(person&&)'
BinaryTree.cpp:10:8: note: candidate expects 1 argument, 0 provided
The lines of code it is referring to, are these structs I created. I have used the person struct before and it works just fine so I am confused as to my error.
struct person {
int socialSecurity, birthDate, zipCode;
string firstName, lastName;
person(int ss, int bd, string fn, string ln, int zc) {
socialSecurity = ss;
birthDate = bd;
firstName = fn;
lastName = ln;
zipCode = zc;
}
};
struct node {
person info;
node * left, * right;
node (person i, node * l, node * r){
info = i;
left = l;
right = r;
}
};
I am a bit new to this so if you need more code to help me figure out what is wrong Ill try to provide as much as I can.

Since you defined a non-default constructor, the compiler will not generate a default constructor, see https://en.cppreference.com/w/cpp/language/default_constructor for more info.
To solve this, see default constructor not generated?.

Related

How to initialize the array-like member variable in the constructor?

How to initialize the array-like member variable?
The visual studio code says:
no matching function for call to 'Node::Node()' gcc line 12 col 9
const int N = 100;
struct Node {
int val, ch[2];
/**
void init(int _val) {
this->val = _val, this->ch[0] = this->ch[1] = 0;
}*/
Node (int _val): val(_val) {
this->ch[0] = this->ch[1] = 0;
}
} tree[N]; // <--------- this is line 12
int main() {
int a;
cin >> a;
tree[0] = Node(a);
}
The problem is that when you wrote tree[N] you're creating an array whose elements will be default constructed but since there is no default constructor for your class Node, we get the mentioned error.
Also, Node doesn't have a default constructor because you've provided a converting constructor Node::Node(int) so that the compiler will not automatically synthesize the default ctor Note::Node().
To solve this you can add a default ctor Node::Node() for your class.

Overloading operator and modifiyng string

I am learning about operator overlaoding. I have created simple class to test it.
class Beer{
public:
Beer(int oner , int twor , string name){
this -> one = oner;
this -> two = twor;
this -> name = name;
};
int getOne(){
return this -> one;
};
int getTwo(){
return this -> two;
};
string getName(){
return this -> name;
};
Beer operator + (const Beer &a)const {
return Beer(5,two+a.two,"firstName");
};
Beer operator + (string a)const {
this -> name = this -> name +" "+a;
};
private:
int one;
int two;
string name;
};
I am trying to figure out , how to midify the string with overloaded operand. My function i declared
Beer operator + (string a)const {
this -> name = this -> name +" "+a;
};
Throws error about passing const string.
I tried using
Beer operator + ( const string *a)const {
swap(this -> name , this -> name + " " + a);
return *this;
};
Which complained about one being cosnst string , and secon one being basic string.
The idea is simple.
Beer one ( 5, 6, "one")
one + "two"
// one.name = "one two"
What is the right way how to do it?
// error with swap
error: no matching function for call to 'swap(const string&, std::basic_string<char>)'|
// erro with string
passing 'const string {aka const std::basic_string<char>}' as 'this' argument of 'std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(std::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' discards qualifiers [-fpermissive]|
Comments:
Don't include the entire std namespace. You're likely to run into nasty name clashes with your own code. At most, use the symbols you need explicitly, e.g. using std::string;.
Unless you need a copy of a value to modify, pass large objects like std::string by const reference. When you declare a parameter as having a value type std::string, you receive a copy of the string, and that's expensive unless you need a copy to modify inside of your function.
This is a long-standing problem with the C++ standard: an implementation detail like this, that should be irrelevant to the user of the function, leaks into the interface (the declaration of the function). Still, when having a copy makes sense, let the compiler give you one without having to type as much. Thus:
// prefer this
std::string fooize(std::string foo) {
assert(foo.size() > 0);
foo.insert(1, "foo");
return foo;
}
// over this
std::string fooize(const std::string & bar) {
assert(bar.size() > 0);
auto foo = bar;
foo.insert(1, "foo");
return foo;
}
Use an initializer list, you then won't need to do silly name gymnastics (you had oner, twor names:
Beer(int one, int two, const std::string & name) :
one(one),
two(two),
name(name)
{}
Declare read-only accessors const:
int getOne() const { return one; }
Return large values like strings by const reference; the user code will likely have the compiler help out with making a copy when needed automatically:
const std::string & getName() const { return name; }
// use:
Beer beer{0,0,""};
std::cout << (beer.getName() + "!") << std::endl; // makes a copy of name as needed
In the + operator taking a string, you're supposed to return a new object, not modify this. You pretty much should do it the way the other operator + you have did it.
Beer operator +(const std::string & a) const {
return Beer(one, two, name + " " + a);
};
If you want to modify your object, you want operator +=:
Beer & operator+=(const std::string & a) {
name += " ";
name += a;
return *this;
}
Even though your class was designed to experiment with operators, you should always consider whether the operators make life easier or not. For example, you class has three members. It's not immediately apparent which of these members would be operated on, unless it was otherwise clear from the class's semantics. It'd be much clearer to have methods named addToOne, addToTwo, and appendToName, for example, instead of operator(s), or simply letting the user set the member through setters, like setOne(int one) { this->one = one; }. The user would then simply do beer.setOne(beer.getOne() + 2);.
Consider naming getters without the get prefix, e.g.
class Beer {
int m_one;
public int one() const { reeturn m_one; }
};
It's less typing for the user. The standard library, as well as large libraries like boost and Qt follow this convention, e.g. you have std::string::size(), not std::string::getSize(), etc.
Beer operator + (string a)const {
this -> name = this -> name +" "+a;
};
You should not change the contents of the object who's + operator is beeing called, afterall if you perform A = B + C, the contents of B should not change. The compiler is correctly informing you about this because it is a const function.
Rather create a temp object to hold the 'sum' and return it.
Beer operator + (string a)const {
return Beer(one, two, name + " " + a);
};
In your operator+() here:
Beer operator+( string a ) const
{
this->name = this->name + " " + a;
};
the const on the function signature is a guarantee to the compiler that when the function is invoked, you won't change the data in the object, yet you change the data in the object.

Graph / Edge class constructor in C++

I am working in a graph class , and i have just started to build a class for vertex , and another class for edge , my question is general not related to graph.
first i build a class its name Vertex , i didn't face any problem in implementing it so far , then i started another class its name is Edge , Edge has three main members two of them has the type Vertex , and the third member has the type unsigned int.
here is the code :
#include<iostream>
using namespace std;
class Vertex
{
private:
unsigned int id;
public:
unsigned int get_id(){return id;};
void set_id(unsigned int value) {id = value;};
Vertex(unsigned int init_val) {id = init_val;};
~Vertex() {};
};
class Edge
{
private:
Vertex first_vertex; // a vertex on one side of the edge
Vertex second_vertex; // a vertex on the other side of the edge
unsigned int weight; // the value of the edge ( or its weight )
public:
Edge(Vertex vertex_1, Vertex vertex_2, unsigned int init_weight) //constructor
{
first_vertex(vertex_1.get_id());
second_vertex(vertex_2.get_id());
weight = init_weight;
}
~ Edge(); // destructor
};
///////////////////////////////// this part is to test the result
Vertex ver_list[2] = {7, 9};
Vertex test = 101;
int main()
{
cout<< "Hello, This is a graph"<< endl;
for (unsigned int i = 0; i < 2; i++) cout<< ver_list[i].get_id() << endl;
cout<< test.get_id() << endl;
return 0;
}
before adding the constructor Edge the code was running without errors , after adding the constructor Edge i received errors when trying to run the code , i am not able to determine my mistake above .
Thanks for your suggestions.
here is the errors message i am receiving:
hw2.cpp: In constructor 'Edge::Edge(Vertex, Vertex, unsigned int)':
hw2.cpp:31:6: error: no matching function for call to 'Vertex::Vertex()'
{
^
hw2.cpp:31:6: note: candidates are:
hw2.cpp:13:2: note: Vertex::Vertex(unsigned int)
Vertex(unsigned int init_val) {id = init_val;}; // constructor
^
hw2.cpp:13:2: note: candidate expects 1 argument, 0 provided
hw2.cpp:6:7: note: Vertex::Vertex(const Vertex&)
class Vertex
^
hw2.cpp:6:7: note: candidate expects 1 argument, 0 provided
hw2.cpp:31:6: error: no matching function for call to 'Vertex::Vertex()'
{
^
hw2.cpp:31:6: note: candidates are:
hw2.cpp:13:2: note: Vertex::Vertex(unsigned int)
Vertex(unsigned int init_val) {id = init_val;}; // constructor
^
hw2.cpp:13:2: note: candidate expects 1 argument, 0 provided
hw2.cpp:6:7: note: Vertex::Vertex(const Vertex&)
class Vertex
^
hw2.cpp:6:7: note: candidate expects 1 argument, 0 provided
hw2.cpp:32:41: error: no match for call to '(Vertex) (unsigned int)'
first_vertex(vertex_1.get_id());
^
hw2.cpp:33:42: error: no match for call to '(Vertex) (unsigned int)'
second_vertex(vertex_2.get_id());
Maybe the problem is the syntax in your constructor:
Edge(Vertex vertex_1, Vertex vertex_2, unsigned int init_weight) //constructor
{
first_vertex(vertex_1.get_id());
second_vertex(vertex_2.get_id());
weight = init_weight;
}
You should initialize the members in an initializer list.
Edge(Vertex vertex_1, Vertex vertex_2, unsigned int init_weight) : first_vertex(vertex_1.get_id()), second_vertex(vertex_2.get_id()), weight(init_weight)
{
}
and you should pass const references to Vertex:
Edge(const Vertex& vertex_1, const Vertex& vertex_2, unsigned int init_weight)
hw2.cpp:32:41: error: no match for call to '(Vertex) (unsigned int)'
first_vertex(vertex_1.get_id());
That error message is addressed below:
Edge(const Vertex& vertex_1, const Vertex& vertex_2, unsigned int init_weight) //constructor
: first_vertex(vertex_1.get_id()), second_vertex(vertex_2.get_id()), weight(init_weight)
{
}
You were trying to initialize your vertexes using their constructors inside the Edge constructor's body (instead of in it's initializer list). That is not valid syntax. You would either need to use the initializer list (show, and preferred), or use their assignment operator in the body of the constructor (syntactically correct, but not preferred as the Vertex would be constructed with incorrect data, and then initialized, instead of simply constructed with the correct data).
An even better approach would be to utilize the copy-constructor of Vertex (instead of your conversion constructor):
// notice the lack of calling the get_id function
Edge(const Vertex& vertex_1, const Vertex& vertex_2, unsigned int init_weight)
: first_vertex(vertex_1), second_vertex(vertex_2), weight(init_weight)
{
}
Additionally, with the following error message:
hw2.cpp:31:6: error: no matching function for call to 'Vertex::Vertex()
You have declared a non-default, non-copy-constructor ( Vertex(unsigned int init_val)), so the compiler will not generate a default constructor for you. Since it will try to initialize a Vertex with the default constructor when you attempt to initialize first_vertex and second_vertex in the body of the Edge constructor, and it does not exist, you get an error. You can fix that by declaring a Vertex() {} constructor.
Probably this is the fix:
Edge(Vertex vertex_1, Vertex vertex_2, unsigned int init_weight) //constructor
{
first_vertex = Vertex(vertex_1.get_id());
second_vertex = Vertex(vertex_2.get_id());
weight = init_weight;
}
You are trying to set your vertex values in edge the wrong way. Use something like
first_vertex.set_id(vertex_1.get_id());
Also, there are standard representations for this type of problem. See more here: http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29#Representations

C++ struct constructor

I tried to create my own structure. So I wrote this piece of code.
struct node
{
int val, id;
node(int init_val, int init_id)
{
val = init_val;
id = init_id;
}
};
node t[100];
int main()
{
...
}
I tried to compile my program. But I got an error:
error: no matching function for call to 'node::node()'
note: candidates are:
note: node::node(int, int)
note: candidate expects 2 arguments, 0 provided
note: node::node(const node&)
note: candidate expects 1 argument, 0 provided
node t[100];
will try to initialise the array by calling a default constructor for node. You could either provide a default constructor
node()
{
val = 0;
id = 0;
}
or, rather verbosely, initialise all 100 elements explicitly
node t[100] = {{0,0}, {2,5}, ...}; // repeat for 100 elements
or, since you're using C++, use std::vector instead, appending to it (using push_back) at runtime
std::vector<node> t;
This will fix your error.
struct node
{
int val, id;
node(){};
node(int init_val, int init_id)
{
val = init_val;
id = init_id;
}
};
You should declare default constructor.

Error when resizing vector of template object

I am trying to create a vector of vector of a template object. The error occurs when I try to resize the inner vector and I can't make heads or tail of the error message. I don't know where it gets the HashTable::Item::Item from. Any suggestions?
/usr/include/c++/4.4.6/bits/stl_vector.h(552): error: no instance of constructor "HashTable::Item::Item [with Key=int, Value=Varvalue]" matches the argument list
resize(size_type __new_size, value_type __x = value_type())
detected during:
instantiation of "void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type={size_t={unsigned long}}, std::vector<_Tp, _Alloc>::value_type) [with _Tp=HashTable<int, Varvalue>::Item, _Alloc=std::allocator<HashTable<int, Varvalue>::Item>]" at line 118 of "main.cc"
Here is the relevant code:
#define VECLEN 16
class Varvalue
{
public:
char data[32];
};
template
class HashTable
{
private:
class Item
{
public:
bool valid;
Key key;
Value value;
Item *next;
Item(const Key k, const Value v, Item *b = 0, bool val = true):
key(k), value(v), next(b), valid(val) {}
};
vector<vector<Item> > table;
int tableSize;
HashTable(const int s): tableSize(s)
{
table.resize(tableSize);
for(int i=0; i<table.size(); i++)
table[i].resize(VECLEN); // <<-- error line 118
}
}
int main()
{
HashTable<int, Varvalue> htable(nkeys);
}
Item doesn't have a default constructor, so you need to provide 2 arguments to resize a vector<Item>. The latter argument shall be a "default" Item with which to fill the vector.
In C++, when you declare a class and you don't provide a constructor a default constructor (without any input parameters) is automatically generated. When you do declare a constructor with input parameters you are not awarded the default constructor. In your case, you did declare a constructor for class item which needs k and v as input parameters but you failed to give them, so either declare a constructor with no input parameters for item or supply k and v.