I'm new to C++ and trying to code a HashTable data structure.
I've written it to be generic using templates, and I've included a HashEntry object to use in it to allow for easy quadratic probing for collisions.
The code I have is:
(in a .C file that #include's the below class definition .H file):
HashEntry::HashEntry()
{
this->isActive = false;
}
And the associated .H file with the class definitions is:
#include <iostream>
#include <string>
#include "Entry.C"
using namespace std;
#define Default_Size 50000
class HashEntry;
template <class T> class HashTable
{
private:
int size;
int occupied;
T array[Default_Size];
public:
HashTable();
int Size();
void Add(T t);
void DebugAdd(T t, int index);
T* Get(string index);
/* How do I declare the existence of HashEntry BEFORE here? */
int FindNextOpen(HashEntry he); // Only works for hash_entry objects!
int Hash(string str);
void Rehash();
};
class HashEntry
{
private:
Entry e;
bool isActive;
public:
HashEntry();
HashEntry(Entry e);
bool IsActive();
Entry GetEntry();
};
Whenever I try and compile everything, I get the error for the HashEntry constructor above:
"no matching function for call to Entry::Entry()" ... "candidates are.....".
I have no idea what it means -- when I try to include a default Entry() constructor (my first interpretation), it throws more errors.
Thanks for the help!
UPDATE -- ENTRY.C:
#include "Entry.H"
/* ***Entry Methods*** */
/*
* Overloaded Entry obejct constructor that provides a string value.
*/
Entry::Entry(string s)
{
this->value = s;
this->count = 0;
}
/*
* Returns the number of times this Entry has been accessed/
* found.
*/
int Entry::Count()
{ return this->count; }
/*
* Returns the string value stored in the Entry object.
*/
string Entry::Value()
{ return this->value; }
And the associated .H file with the class definitions is:
#include <iostream>
#include <string>
#include "Entry.C"
Whoa! Never, ever #include a source file in a header.
Your Entry.C should not exist. Instead define the constructor in your header, inside the class definition:
class HashEntry
{
private:
Entry e;
bool isActive;
public:
HashEntry() : isActive(true) {}
...
}
One thing that you haven't shown us is the definition of the class Entry. That is one of the sources of your problem. It's a bit hard to pin down your problem when you didn't show us the very thing that is causing it.
I found the problem.
The error message says there is not matching function call for "Entry::Entry()". Because in no case was I actually creating Entry objects I had no idea what it meant.
I tried adding an explicit default constructor for class Entry and it resolved.
Thanks for the help everyone!
Related
I have TestMethods.h
#pragma once
// strings and c-strings
#include <iostream>
#include <cstring>
#include <string>
class TestMethods
{
private:
static int nextNodeID;
// I tried the following line instead ...it says the in-class initializer must be constant ... but this is not a constant...it needs to increment.
//static int nextNodeID = 0;
int nodeID;
std::string fnPFRfile; // Name of location data file for this node.
public:
TestMethods();
~TestMethods();
int currentNodeID();
};
// Initialize the nextNodeID
int TestMethods::nextNodeID = 0;
// I tried this down here ... it says the variable is multiply defined.
I have TestMethods.cpp
#include "stdafx.h"
#include "TestMethods.h"
TestMethods::TestMethods()
{
nodeID = nextNodeID;
++nextNodeID;
}
TestMethods::~TestMethods()
{
}
int TestMethods::currentNodeID()
{
return nextNodeID;
}
I've looked at this example here: Unique id of class instance
It looks almost identical to mine. I tried both the top solutions. Neither works for me. Obviously I'm missing something. Can anyone point out what it is?
You need to move the definition of TestMethods::nextNodeID into the cpp file. If you have it in the header file then every file that includes the header will get it defined in them leading to multiple defenitions.
If you have C++17 support you can use the inline keyword to declare the static variable in the class like
class ExampleClass {
private:
inline static int counter = 0;
public:
ExampleClass() {
++counter;
}
};
This question already has answers here:
Why does the C++ map type argument require an empty constructor when using []?
(6 answers)
Closed 5 years ago.
I've done a lot of Googling and can't seem to figure out what's going on. I'm teaching myself C++ (I'm more familiar with Java).
I have Item Class objects that are being stored in an Inventory Class map, not as pointers. I want to retrieve one of the items from the Inventory in a function, assign it to a temp variable while I delete it from the Inventory map, and then return the object itself so something else can use it. When I originally tried using the code within my function it was returning the error (followed by the stack trace of c++ library stuff):
no matching constructor for initialization of 'Item'
::new ((void*)__p) _Tp();
I tried creating a copy constructor, but to no avail. Eventually, it worked by including an empty constructor ( Item(); ) in my header file and defining it in my cpp file ( Item::Item() {} ).
I would just like to understand why this was necessary so I can recognize it in the future to know what I'm doing.
EDIT: Upon further inspection of the error stack trace, it turned out the actual problem with with the Inventory::addItem function. When assigning an object to a map using operator[], the map first instantiates the value type to the key using the default constructor before making the assignment. No default constructor was available, so the error was returned.
It was fixed by changing the line to map.insert({key, value})
Here are the important parts of the two class files:
//item.h
#include <string>
using namespace std;
class Item {
private:
string name;
int type;
int levelReq;
public:
Item(string name, int type, int levelReq);
Item();
string getName() {return name;}
int getType() {return type;}
friend ostream &operator<<(ostream &out, const Item &item);
};
---------------------------------------------------------------
//item.cpp
#include <string>
#include "item.h"
using namespace std;
Item::Item(string n, int t, int l) : name(n), type(t), levelReq(l) {}
Item::Item() {}
ostream &operator<<(ostream &out, const Item &item) {
return out << item.name;
}
---------------------------------------------------------------
//inventory.h
#include <map>
#include "item.h"
class Inventory {
private:
map <int, Item> inventory;
int size;
bool full;
int nextFree;
void findNextFree();
public:
Inventory();
bool isFull() {return full;}
void addItem(Item item);
Item getItem(int slot);
void showInv();
};
---------------------------------------------------------------
//inventory.cpp
#include <iostream>
#include <string>
#include "inventory.h"
#include "item.h"
using namespace std;
Inventory::Inventory() {
full = false;
nextFree = 1;
size = 28;
}
void Inventory::addItem(Item item) {
if (!full) {
inventory[nextFree] = item;
findNextFree();
}
else {
cout << "Your inventory is full (Inv::addItem)";
}
}
Item Inventory::getItem(int slot) {
Item item = inventory.at(slot);
inventory.erase(slot);
full = false;
if (nextFree > slot) {
nextFree = slot;
}
return item;
}
void Inventory::findNextFree() {
nextFree++;
if (nextFree == size + 1) {
full = true;
}
else if (inventory.count(nextFree)) {
findNextFree();
}
}
I think the issue rose because you declared a constructor for your item class.
C++ will automatically generate the necessary constructors if you don't provide any custom constructors.
The necessary constructors are the default, copy and move constructors.
The moment you provide one, the default constructors won't be generated and you have this issue. This principle will also apply to structs.
Check the reference to see for yourself:
http://en.cppreference.com/w/cpp/language/default_constructor
http://en.cppreference.com/w/cpp/language/copy_constructor
http://en.cppreference.com/w/cpp/language/move_constructor
Hope this answers your question.
I have the following files:
ListaEnc.hpp
#include "Elemento.hpp"
#include <cstdlib>
#include <iostream>
template<typename T>
class ListaEnc {
public:
ListaEnc();
~ListaEnc();
...
}
//Implementation:
template<typename T>
ListaEnc<T>::ListaEnc()
{
head = NULL;
size = 0;
}
template <class T>
ListaEnc<T>::~ListaEnc() {
}
main.cpp:
#include "ListaEnc.hpp"
using namespace std;
int main(int argc, char** argv)
{
ListaEnc<int>* teste = new ListaEnc<int>();
return 0;
}
Poligono.hpp
#ifndef POLIGONO_HPP
#define POLIGONO_HPP
#include "Ponto.hpp"
#include "ListaEnc.hpp"
#include <string>
using namespace std;
public:
//Construtores
Poligono(ListaEnc<Ponto> pontos, string nome);
Poligono(const Poligono& orig);
virtual ~Poligono();
//Metodos
string obterNome();
void adicionarPonto(Ponto);
ListaEnc<Ponto> obterPontos();
private:
ListaEnc<Ponto> pontos;
string nome;
};
#endif /* POLIGONO_HPP */
Poligono.cpp
#include "Poligono.hpp"
* Poligono::Poligono(ListaEnc<Ponto> pontos, string nome)
{
this->pontos = pontos;
this->nome = nome;
}
* Poligono::Poligono(const Poligono& orig) {
}
* Poligono::~Poligono() {
}
//Metodo
string Poligono::obterNome()
{
return this->nome;
}
ListaEnc<Ponto> Poligono::obterPontos()
{
return this->pontos;
}
void Poligono::adicionarPonto(Ponto p)
{
this->pontos.adiciona(p);
}
I get these compile errors on Poligono.cpp:
/home/mariana/NetBeansProjects/TrabalhoCG/Poligono.cpp:12: undefined reference to `ListaEnc::~ListaEnc()'
The destructor for ListaEnc is empty, but is implemented. Does anyone know how to solve this problem?
Edit: Added the implementation of constructor and destructor for ListaEnc. The error appears in the bit of code I added for Poligono.cpp, where ListaEnc is one of the parameters.
Edit2: I have added an asterisk to the points in Poligono.cpp where the error appears (The first constructor, second constructor and destructor)
Since you posted code that shows
#ifndef POLIGONO_HPP
#define POLIGONO_HPP
in Poligono.cpp, but you don't have the same in ListaEnc.hpp, I assume that you are missing include guards in that header?
Depending on what other code is included in Poligono.cpp, this could result in the definition of template ListaEnc twice. Under C++ standard if you break the one definition rule you may just get a linking error and no other diagnostic message.
So, maybe make sure that there are include guards in ListaEnc.hpp ?
If you post more code I will update this answer :)
Edit: Another suggestion, if it is having trouble finding the dtor definition of ListaEnc, you might try moving the implementation of it into the class body? This makes it less likely that a typo will cause it to be lost. Since all the code is in the header this really doesn't change anything otherwise.
I'm new in C++ and I have something to do with a linked list, and I don't know why it doesn't work, need help from a prof :O)
Here's my .h
#ifndef UnCube_H
#define UnCube_H
using namespace std;
class ACube{
public:
ACube();
struct Thecube;
private:
void PrintList();
};
#endif
My ACube.cpp
#include <iostream>
#include "ACube.h"
ACube::ACube(){
};
struct Thecube{
int base;
int cube;
Thecube * next ;
};
void ACube::PrintList(){
};
and finally my main.cpp
#include <cstdlib>
#include <iostream>
#include "ACube.h"
using namespace std;
int main()
{
ACube * temp;
temp = (ACube*)malloc(sizeof(ACube));
for (int inc=1; inc <=20 ; inc++){
temp->ACube->nombrebase = inc;
temp->cube = inc*inc*inc;
}
system("PAUSE");
return EXIT_SUCCESS;
}
Everything was working fine, but when I add these lines :
temp->ACube->nombrebase = inc;
temp->cube = inc*inc*inc;
I add error saying :
'class ACube' has no member named 'TheCube'
'class ACube' has no member named 'cube'
Can someone help me because I want to create my list and fill the cube with number.
Other thing I want to use THIS. in the print,
Maybe someone can teach me what's wrong and how to do it !
Thanks for any help
You don't need to have a struct inside your class.
#ifndef UnCube_H
#define UnCube_H
using namespace std;
class ACube{
public:
ACube();
int base;
int cube;
ACube * next ;
private:
void PrintList();
};
#endif
ACube.cpp
#include <iostream>
#include "ACube.h"
ACube::ACube(){
};
void ACube::PrintList(){
};
Also, this string is wrong:
temp->ACube->nombrebase = inc;
it should be just:
temp->base = inc;
Last but not least, this code doesn't create a linked list, because you don't do anything with the ACube::next pointer.
There are so many horrible problems in your code, I suggest you should learn more C++ knowledge before writing linked list.
1. What is nombrebase?
I think nobody can answer.
2. You must allocate C++ class by new key word instead of malloc.
new invokes not only allocation but also class constructor, while malloc allocates only.
3. Thecube should been defined inside ACube
Since the code in your main() refers the member cube in class Thecube, main() must know what it is.
4. The member next in class ACube is a pointer which points to what?
What does a pointer point to without initilization? You should initial it in constructor, and destroy it in destructor.
5. temp->ACube
ACube is a class type, you can access member object, but not a type.
6. Never using namespace into a header file
It would make the client of header file has name collision.
The following is the corrected code. Just no compile error and runtime error, but this is NOT linked list:
ACube.h
#ifndef UnCube_H
#define UnCube_H
class ACube{
public:
struct Thecube
{
int base;
int cube;
Thecube * next;
};
ACube();
~ACube();
Thecube *next;
private:
void PrintList();
};
#endif
ACube.cpp
ACube::ACube()
: next(new Thecube)
{
}
ACube::~ACube()
{
delete next;
}
void ACube::PrintList(){
}
main.cpp
#include <cstdlib>
#include <iostream>
#include "ACube.h"
using namespace std;
int main()
{
ACube * temp;
temp = new ACube;
for (int inc = 1; inc <= 20; inc++)
{
temp->next->base = inc; // <-- This is not linked list, you shall modify.
temp->next->cube = inc*inc*inc; // <-- This is not linked list, you shall modify.
}
system("PAUSE");
return EXIT_SUCCESS;
}
I need to call a method from one class in the constructor of another class. I am not sure how to do this without getting a "was not declared in this scope" error. Note I am just learning C++.
See the comments in symboltable.cpp for what I am trying to accomplish here. I am not looking for anyone to do it for me. I could use an example or pointed in the right direction so I can figure this out.
symboltable.h code:
class SymbolTable
{
public:
SymbolTable() {}
void insert(string variable, double value);
void insert(string variable); // added for additional insert method
double lookUp(string variable) const;
void init(); // Added as mentioned in the conference area.
private:
struct Symbol
{
Symbol(string variable, double value)
{
this->variable = variable;
this->value = value;
}
string variable;
double value;
};
vector<Symbol> elements;
};
symboltable.cpp code:
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
#include "symboltable.h"
/* Implementing the "unreferenced variable" warning.
* Modify the symbol table by adding another insert method
* that supplies only the variable name.
* This method should be called when the variable name
* is encountered while building the arithmetic expression tree.
* It would be called in the constructor of the Variable class.
* The existing insert method, which is called when an assignment is encountered,
* would first check to see whether it is already in the symbol table.
* If it is not, then it is unreferenced.
*/
void SymbolTable::insert(string variable, double value)
{
/* This existing insert method, which is called when an assignment is encountered,
* first needs to check to see whether it is already in the symbol table.
* If it is not, then it is unreferenced.
* */
//Need to check if variable is in the expression need to find out how the expression is stored!
if (find(elements.begin(), elements.end(), variable)) {
const Symbol& symbol = Symbol(variable, value);
elements.push_back(symbol);
} else
throw string("Error: Test for output");
}
/* Adding another insert method that supplies only the variable name.
* This method should be called when the variable name is encountered
* while building the arithmetic expression tree.
* It should be called in the constructor of the Variable class.
*/
void SymbolTable::insert(string variable)
{
const Symbol& symbol = Symbol(variable, symbolTable.lookUp(variable));
elements.push_back(symbol);
}
double SymbolTable::lookUp(string variable) const
{
for (int i = 0; i < elements.size(); i++)
if (elements[i].variable == variable)
return elements[i].value;
else
throw "Error: Uninitialized Variable " + variable;
return -1;
}
void SymbolTable::init() {
elements.clear(); // Clears the map, removes all elements.
}
variable.h code:
class Variable: public Operand
{
public:
Variable(string name) //constructor
{
// how do i call symbolTable.insert(name); here
// without getting 'symboleTable' was not declared in this scope error
this->name = name;
}
double evaluate();
private:
string name;
};
variable.cpp code:
#include <string>
#include <strstream>
#include <vector>
using namespace std;
#include "expression.h"
#include "operand.h"
#include "variable.h"
#include "symboltable.h"
extern SymbolTable symbolTable;
double Variable::evaluate() {
return symbolTable.lookUp(name);
}
There are two solutions:
You use a global variable - like your Variable::evaluate() example. You can of course add your Variable::Variable() as a function in "variable.cpp" instead of the header. Or you can just put a extern SymbolTable symbolTable to the file "variable.h".
You pass in a reference to symbolTable into the constructor (and perhaps store that inside the Variable object - that way, symbolTable doesn't need to be a global variable at all.
By the way, it's generally considered bad style to add using namespace std before header files.
extern SymbolTable symbolTable; needs to go into the header file that is included by everyone who needs symbolTable. Then, in variable.cpp, you need to have SymbolTable symbolTable;
You need to instantiate the second class, either within the constructor, which will make it and its members available only within the constructor of the first class, or in the global namespace. For example:
MyFooClass CFoo;
MyBarClass CBar;
MyFooClass::MyFooClass()
{
CBar = new MyBarClass();
CBar.BarClassMemberFunction();
}