C++ Function already has a body [duplicate] - c++

This question already has answers here:
Including .cpp files
(10 answers)
Why should I not include cpp files and instead use a header?
(14 answers)
Closed 2 years ago.
I have an error where "function already has a body" for my constructors and member functions when I have not repeated any of the bodies. The error code is C2084:
void Func(int);
void Func(int) {} // define function
void Func(int) {} // C2084 second definition
I have not created duplicate functions similar to what is shown on the visual studios error page. here is the code below if anybody knows a solution to this error I would greatly appreciate it.
Here is the Stack.h:
//CONTENTS: Declares Class SStack, with data members, contructors and member function prototypes
//If you want, you can make minor changes to this header file
#ifndef _StackClass_
#define _StackClass_
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
class SStack
{
public:
// Constructor
SStack( int cap);
// Copy Constructor
SStack( const SStack& s );
~SStack( ); //destructor
// The member function push: Precondition: the stack is not full.
void push ( const std::string s);
// The member function pop: Precondition: the stack is not empty.
void pop ();
// The member function top: Precondition: the stack is not empty.
string top () const;
bool IsEmpty () const;
//printing all the elements in the stack
void print() const;
int size() const;
int getCapacity() const;
private:
int capacity; // Capacity is the maximum number of items that a stack can hold
std::string* DynamicStack;
int used; // How many items are stored in the stack
};
#include "SStack.cpp"
#endif
Here is the SStack.cpp:
#include <iostream>
#include "SStack.h"
SStack::SStack(int cap)
{
DynamicStack = new string[cap];
this->capacity = cap;
this->used = -1;
}
SStack::SStack(const SStack& s)
{
capacity = s.capacity;
DynamicStack = new string[capacity];
used = s.used;
for (int i = 0; i < used; i++) {
DynamicStack[i] = s.DynamicStack[i];
}
}
SStack::~SStack()
{
}
void SStack::push(const std::string s)
{
if (used >= capacity - 1) {
cout << "Stack overflow" << endl;
}
else {
this->used++;
DynamicStack[used] = s;
cout << s << "pushed onto the stack" << endl;
}
}
void SStack::pop()
{
if (used < 0) {
cout << "stack underflow" << endl;
}
else {
string s = DynamicStack[used];
this->used--;
}
}
string SStack::top() const
{
if (used < 0) {
cout << "stack is empty" << endl;
return 0;
}
else {
string s = DynamicStack[used];
return s;
}
}
bool SStack::IsEmpty() const
{
if (used < 0) {
return true;
}
else {
return false;
}
}
void SStack::print() const
{
for (int i = used; i >= 0; i--) {
cout << DynamicStack[used] << endl;
}
}
int SStack::size() const
{
return used;
}
int SStack::getCapacity() const
{
return capacity;
}

You have an #include "SStack.cpp" in your header file.
Don't do that.
Source files (.cpp files) include header files. Never the other way around.

Related

c++ Template Class Syntax for Methods

I am learning templates and am struggling to set up my put method without compiler errors. Can someone point me in the right direction? The commented sections are not implemented yet, but based on an Integer-key, String-value implementation.
The concrete error I am having: Severity Code Description Project File Line Suppression State
Error C2923 'HashTable<int,std::string>::HashItem': 'key' is not a valid template type argument for parameter 'Key'
#pragma once
#include <cmath>
#include <iostream>
#include <list>
using namespace std;
template<typename Key, typename Value>
class HashTable
{
template<typename Key, typename Value>
class HashItem {
public:
Key key;
Value value = nullptr;
bool operator==(const HashItem& hi) const { return key == hi.key && value == hi.value; }
HashItem(const Key& k, const Value& v)
: key(k), value(v) {}
// for part b)
HashItem& operator=(const Value& v) {
this->value = v;
return *this;
}
operator string() { return this->value; }
};
list<HashItem<Key, Value>>* table;
int current_total = 0;
float FILL_LEVEL = 0.8; // Füllgrad, between 0 and 1
// not const:
int CAPACITY = 100; // default value
// for hash functions/preparing for use with strings:
const int PRIME_CONST = 31;
int hash_function(string key);
int hash_function(int key);
// std::hash?
void rehash();
public:
HashTable() {
cout << "ht cstructed, intitial_capacity is (default:) " << CAPACITY << endl;
}
HashTable(int initial_capacity) {
cout << "ht cstructed, intitial_capacity is " << initial_capacity << endl;
CAPACITY = initial_capacity;
}
//// RULE OF THREE
//// copy ctor
//HashTable(HashTable& const ht);
//// destructor
//~HashTable();
//// (copy) assignment operator
//HashTable& operator=(HashTable& const ht);
//// RULE OF FIVE
//// move ctor
//HashTable(HashTable&& ht); // && -> rvalue
//// move assignment operator
//HashTable& operator=(HashTable&& ht);
//// Hash Table operations
void put(Key key, Value value) {
// allocate memory with first put
if (current_total == 0)
table = new list<HashItem<key, value>>[CAPACITY];
HashItem<key, value>* hi = new HashItem(key, value);
int hash = hash_function(key);
if (find(table[hash].begin(), table[hash].end(), *hi) == table[hash].end()) {
// only put if not already in list
table[hash].push_back(*hi);
}
current_total++;
//cout << "current total is " << current_total << " of " << FILL_LEVEL * CAPACITY << endl;
// rehash check
if (current_total > (FILL_LEVEL * CAPACITY)) {
rehash();
//cout << "fill level reached: rehashed" << endl;
}
}
//void remove(int key, string value);
//string get(int key);
//// for part b)
//HashItem& get_item(int key) {
// int list_index = hash_function(key); // list_index = hash_code
// if (!table[list_index].empty()) {
// for (auto &list_item : table[list_index]) {
// if (key == list_item.key) {
// return list_item;
// }
// }
// }
// HashItem hi(key, "");
// return hi;
//}
//friend ostream& operator<<(ostream& os, const HashTable& ht);
//void clear();
//bool contains(int key);
//bool contains_value(string value);
//// fill levels
//void set_fill_level(float new_level);
//float get_fill_level();
//// b)
//// Overloading [] operator to access elements in array style
//HashItem& operator[] (int key) {
// if (this != nullptr)
// return this->get_item(key);
// HashItem hi(key, "");
// // stand-in hash item in case not in hash table
// return hi;
//}
};
Call in my main.cpp:
#include <iostream>
#include "HashTable.h"
using namespace std;
#define DEBUG(X) cout << (#X) << " = " << (X) << endl
HashTable<int, string> ht;
void put_test() {
cout << "--------------- put test ----------------------------------" << endl;
ht.put(10, "test");
}
int main() {
put_test();
}

Setter not changing the data from a vector within a class

In my program, I have a class that holds a vector of type integer. It is used to store distances. I have a function, that when called, should set values in the vector to 0's. (used for initializing). But when I go to check the size of the vector, it still says the vector is empty.
I have created multiple functions that check whether the vector is adding any elements, and it is not. I have a function, that within main, I call to see if the vector is empty, and it returns 0 (the vector has 0 elements in it).
int MLB::getDistanceSize()
{
return distances.size();
}
void MLB::setInitialDistances(int size)
{
for(int i = 0; i < size; i++)
{
this->distances.push_back(0);
}
}
class MLB
{
public:
//constructor
MLB();
~MLB();
int getDistanceSize();
void setInitialDistances(int size);
private:
vector<int> distances;
};
The input file is a csv file with each line consisting of:
stadium1,stadium2,distance
so sample input file is:
AT&T Park,Safeco Field,680
AT&T Park,Oakland–Alameda County Coliseum,50
Angel Stadium,Petco Park,110
Angel Stadium,Dodger Stadium,50
Busch Stadium,Minute Maid Park,680
Busch Stadium,Great American Ball Park,310
Busch Stadium,Target Field,465
Busch Stadium,Kauffman Stadium,235
etc...
I am using qt, and this is where I am calling the functions themselves. All information is stored into a map, and the other getters work perfectly fine. Sorry for making this a lot more confusing than the problem really is, any help is greatly appreciated.
// key and value, key is the team name, value is the MLB stadium information
struct entry
{
string key;
MLB value;
};
class Map
{
public:
//Public default constructor
Map();
//Public default destructor
~Map();
// returns entry of the map
entry atIndex(int index);
// Inserts a key and its value using linear algorithm
void insert(const string& theKey, const MLB& value);
private:
vector<entry> thisTable;
int currentSize; //Integer variable for current size
};
functions for Map:
Map::Map()
{
currentSize = 0;
}
Map::~Map()
{
}
void Map::insert(const string& theKey, const MLB& value)
{
entry thisEntry;
thisEntry.key = theKey;
thisEntry.value = value;
thisTable.push_back(thisEntry);
currentSize+=1;
}
entry Map::atIndex(int index)
{
return thisTable.at(index);
}
//mainwindow constructor
mainWindow::mainWindow()
{
//Reads in input from first csv file, all works fine all data stored and can access it
string iStadium1;
string iStadium2;
string iDistance;
string previous;
int distance;
int index1;
int index2;
bool found;
ifstream csvFile2;
csvFile2.open("inputDistance.csv");
getline(csvFile2, iStadium1, ',');
while(!csvFile2.eof())
{
index1 = 0;
found = false;
while(!found)
{
if(thisMap.atIndex(index1).value.getStadiumName() == iStadium1)
{
thisMap.atIndex(index1).value.setInitialDistances(thisMap.mapSize());
cout << "Distance Size Test 1: " << thisMap.atIndex(index1).value.getDistanceSize() << endl;
found = true;
}
else
{
index1++;
}
}
previous = iStadium1;
while(iStadium1 == previous)
{
getline(csvFile2, iStadium2, ',');
getline(csvFile2, iDistance, '\n');
distance = stoi(iDistance);
index2 = 0;
found = false;
while(!found)
{
if(thisMap.atIndex(index2).value.getStadiumName() == iStadium2)
{
found = true;
cout << "Distance Size Test 2: " << thisMap.atIndex(index1).value.getDistanceSize() << endl;
// crashes here. Index out of bounds, size is 0 for some reason
thisMap.atIndex(index1).value.setDistance(index2, distance);
}
else
{
index2++;
}
}
getline(csvFile2, iStadium1, ',');
}
}
csvFile2.close();
}
I expect the vector to hold 30 slots (assuming the desired size passed into the function is 30) of value 0, rather than having an empty vector.
The code in your question works as expected after adding constructor and destructor (doing both nothing) :
#include <iostream>
#include <vector>
using namespace std;
class MLB
{
public:
//constructor
MLB();
~MLB();
int getDistanceSize();
void setInitialDistances(int size);
private:
vector<int> distances;
};
int MLB::getDistanceSize()
{
return distances.size();
}
void MLB::setInitialDistances(int size)
{
for(int i = 0; i < size; i++)
{
this->distances.push_back(0);
}
}
MLB::MLB() {
}
MLB::~MLB() {
}
int main()
{
MLB mlb;
mlb.setInitialDistances(30);
cout << mlb.getDistanceSize() << endl;
}
pi#raspberrypi:/tmp $ g++ d.cc
pi#raspberrypi:/tmp $ ./a.out
30
the vector is not empty but contains 30 times 0
if thisMap.atIndex(index1).value.setDistance(index2, distance); does nothing this is probably because atIndex(index1) returns a copy rather than a reference, so you modify a copy and the original is unchanged
For instance :
#include <iostream>
#include <vector>
using namespace std;
class C {
public:
vector<int> getv() { return v; } // return a copy
vector<int> & getvref() { return v; } // return the ref to the vector, not a copy
int len() { return v.size(); }
private:
vector<int> v;
};
int main()
{
C c;
c.getv().push_back(0); // modify a copy of v
cout << c.len() << endl;
c.getvref().push_back(0); // modify v
cout << c.len() << endl;
}
Compilation and execution :
pi#raspberrypi:/tmp $ g++ vv.cc
pi#raspberrypi:/tmp $ ./a.out
0
1
you edited you question and this is what I supposed :
entry Map::atIndex(int index)
{
return thisTable.at(index);
}
return a copy, must be
entry & Map::atIndex(int index)
{
return thisTable.at(index);
}

Changing a value of an element in an object that is stored in a vector in another object through an external function in C++

So made a class called ‘Item’, and the object of that class will have a 100% condition at the start, the Player stores items (with name “apple” in this case) whenever I tell him to. In the degradeT function I want to pass the whole vector containing the items that the player has picked up by far and then change the condition of each Item in that vector by -1 through the chCond function.
first error:
initial value of reference to non-const must be an lvalue
second error:
'void degradeT(std::vector<Item,std::allocator<_Ty>> &)': cannot convert argument 1 from 'std::vector<Item,std::allocator<_Ty>>' to 'std::vector<Item,std::allocator<_Ty>> &'
#include "pch.h"
#include <iostream>
#include <string>
#include <vector>
using std::cout; using std::cin; using std::endl;
using std::string; using std::vector; using std::to_string;
class Item {
private:
string name; // Item name
float condition; // Item condition
bool consumable; // Is the item consumable
public:
Item() {}
Item(string a, float b, bool c) { name = a; condition = b; consumable = c; }
Item(string a, bool c) { name = a; condition = 100.f; consumable = c; }
string getName() {
return name;
}
float getCond() {
return condition;
}
bool isCons() {
return consumable;
}
void chCond(float a) { // Change Item condition
condition += a;
}
};
//-----------------------
class Player {
private:
vector<Item> plItems; // Item container
public:
Player() {}
void pickUpItem(Item a) { // Adding Items to inventory
plItems.push_back(a);
cout << a.getName() << " added to inventory!\n";
}
void checkItemConds() { // Checking condition of all items
for (unsigned int a = 0, siz = plItems.size(); a < siz; a++) {
cout << plItems[a].getName() << "'s condition is: " << plItems[a].getCond() << "%\n";
}
}
Item returnItem(unsigned int a) { // Return a specific Item
return plItems[a];
}
int getCurInvOcc() { // Get cuurent inventory occupation
return plItems.size();
}
vector<Item> getPlItems() { // Return the vector (Item container)
return plItems;
}
};
//-------------------------
void degradeT(vector<Item>& Itemss); // Degrade item after some time
//-------------------------
int main()
{
Player me; // me
string inp; // input
int num = 1; // apple 1, apple 2, apple 3...
while (inp != "exit") {
cin >> inp;
if (inp == "addApple") {
Item apple(("apple " + to_string(num)), true);
me.pickUpItem(apple);
num++;
}
if (inp == "checkItemConds") {
me.checkItemConds();
}
if (inp == "timeTick") {
// This doesn't have anything to do with time I just want to test the function manually
degradeT(me.getPlItems());
}
}
system("PAUSE");
return 0;
}
void degradeT(vector<Item> &Itemss) {
for (unsigned int a = 0, siz = Itemss.size(); a < siz; a++) {
Itemss[a].chCond(-1);
cout << Itemss[a].getName() << endl;
}
}
I'm not sure what your question is, but your error is related to the function void degradeT(vector<Item> & Itemss).
This functions expects a reference but you are passing an r-value. You can either return a reference with getPlItems() or pass an l-value to degradeT.

Unknown Syntax errors in linkedlist Sort program

Assignment was to create a sort function for linked list. Was able to code it, but I am getting a ton of unknown syntax errors. I suspect it could be Visual Studio (professor requires it), but I want to see what you guys think. Most of the errors lie in the header file (SortedList.h), however my professor provided this piece of code, so it doesnt make sense that it doesnt work.
EDIT:
Errors include:
-Missing type specifier - int assumed Note: C++ does not support default int
(sortedlist.h Line:4)
-Syntax error missing ; before identifier ItemType (sortedlist.h Line:4)
-'string' ambiguous symbol (sortedlistprogram.cpp Line:12)
-Syntax error: Identifier 'itemType' (Sortedlist.h Line 14)
-Unexpected token(s) proceeding ';' (sortedlist.h Line 34)
//SortedList.h (header file)
#include <string>
const int MAX_ITEMS = 20;
typedef string ItemType;
class SortedList
{
public:
SortedList();
// Constructor
// Post: Empty list is created.
// Action responsibilities
void Insert(ItemType item);
// Pre: The list is not full;
// Post: item is in the list; list is stored in
// increasing order.
void PrintList();
// Post: If the list is not empty, the elements are
// printed on the screen in increasing order;
// otherwise "The list is empty" is
// printed on the screen.
// Knowledge responsibilities
int GetLength();
// Post: return value is the number of items in the list.
bool IsEmpty();
// Post: returns true if list is empty; false otherwise.
bool IsFull();
// Post: returns true if there is no more room in the
// list; false otherwise.
private:
int length;
ItemType values[MAX_ITEMS];
};
//SortedList.CPP
#include "sortedList.h"
#include <iostream>
#include<string>
#include<algorithm>
using namespace std;
SortedList::SortedList()
{
length = 0;
}
bool SortedList::IsEmpty()
//Function to check if empty
{
if (values->empty())
return true;
return false;
}
bool SortedList::IsFull()
//Function to check if full
{
if (length == MAX_ITEMS)
return true;
return false;
}
void SortedList::Insert(ItemType item)
//Insert function for SortedList
{
if (!IsFull())
{
values[length] = item;
++length;
sort(values, values + length);
}
}
int SortedList::GetLength()
//Function to return length
{
return length;
}
void SortedList::PrintList()
//Function to print list
{
if (IsEmpty())
{
cout << "List is empty" << endl;
}
else
{
for (int index = 0; index < length; ++index)
{
cout << values[index] << endl;
}
cout << endl << "There are " << GetLength() << " items in the list" <<
endl;
}
}
//Driver.CPP
#include "sortedList.h"
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string value;
SortedList list;
list.PrintList();
ifstream file("word.in");
//calls word.in file
if (file.good())
//Checks if file is good
{
while (getline(file, value))
{
list.Insert(value);
}
file.close();
}
list.PrintList();
//Prints list
return 0;
}

Segfault during C++ array deallocation

I'm getting a weird problem in memory deallocation.
I have the following code for class MemoryPartition:
#include <cstring>
#include <iostream>
#include "memorypartition.h"
MemoryPartition::MemoryPartition(int maxSize) {
this->partitionArray = new char[maxSize];
memset(this->partitionArray, ((int) '$'), maxSize);
this->maxSize = maxSize;
this->isFree = true;
}
MemoryPartition::~MemoryPartition() {
delete[] this->partitionArray;
this->partitionArray = NULL;
maxSize = 0;
}
void MemoryPartition::setFree(bool isFree) {
this->isFree = isFree;
}
bool MemoryPartition::getFree() {
return this->isFree;
}
int MemoryPartition::getMaxSize() {
return this->maxSize;
}
void MemoryPartition::getPartitionArray() {
for(int i = 0;i < maxSize;i++) {
std::cout << partitionArray[i] << ' ';
}
std::cout << std::endl;
}
and the following code for MemoryManager:
#include "memorymanager.h"
#include <iostream>
#include <cstdlib>
MemoryManager::MemoryManager() {
}
MemoryManager::~MemoryManager() {
memory.clear();
}
void MemoryManager::defmem(int bytes) {
MemoryPartition *memPartition;
int maxMemorySize = bytes;
while(maxMemorySize != 0) {
int partitionSize = this->randomPartitionSize(maxMemorySize);
memPartition = new MemoryPartition(partitionSize);
this->memory.push_back(*memPartition);
std::cout << memPartition->getMaxSize() << std::endl;
memPartition->getPartitionArray();
maxMemorySize -= partitionSize;
delete memPartition;
memPartition = NULL;
}
}
int MemoryManager::randomPartitionSize(int maxSize) {
int value;
srand(time(NULL));
value = (rand() % maxSize) + 1;
return value;
}
and I'm getting a weird at delete[] in MemoryPartition destructor. Valgrind is telling me there are 13 frees and 10 allocs, but I can't see a reason why this delete[] would be called 3x.
Anyone see the problem I couldn't figure out?
Thanks in advance.
[]'s,
Its impossible to tell from the code above.
But my guess is that you need to define the copy constructor and assignment operator.
See Rule of 4 (Google/Wiki it).
Try the following:
class MemoryPartition
{
// Just add these two lines (keep them private)
MemoryPartition(MemoryPartition const&); // Don't define.
MemoryPartition& operator=(MemoryPartition const&); // Don't define.
<CLASS STUFF AS BEFORE>
};
Compile the code now. If it fails because the above are private then you have accidentally made a copy of the object somewhere and are doing a double delete on the pointer.