ostream operator overloading - inheritance - c++

I have a base class called Item:
#ifndef ITEM_H
#define ITEM_H
#include <ostream>
class Item {
public:
virtual ~Item() {}
virtual void print(std::ostream& out) const {}
friend std::ostream& operator << (std::ostream& out, Item& item){
item.print(out);
return out;
}
};
#endif
and I have a derived class Tower:
#ifndef TOWER_H
#define TOWER_H
#include <iostream>
#include <iostream>
#include <exception>
#include "item.h"
#include "Card.h"
class Tower : public Item {
unsigned height;
void print(std::ostream& o) const;
public:
Tower(const Card& card);
int demolish(Card& card) const;
unsigned getHeight() const;
};
#endif
Source code for Tower:
#include "tower.h"
Tower::Tower(const Card& card){
height = card.getDis();
}
void Tower::print(std::ostream& o) const {
o << height;
}
int Tower::demolish(Card& card) const{
try {
if(height != card.getDis()){
throw std::exception ();
} else {
return height;
}
} catch (std::exception e){
cout<< "Card's value not enough to demolish the tower." << endl;
}
}
unsigned Tower::getHeight() const {
return height;
}
Now I'm trying to test the code to see if the operator overloading works properly:
void test() {
Card card (Card::SOUTH, 3);
Tower tower(card);
std::cout << "Printing tower: " << tower << std::endl; //PRINTS OUT 3 AS EXPECTED
Card one (Card::NORTH, 2);
Card two (Card::WEST, 3);
std::cout << "Expecting to receive an error: " <<endl;
tower.demolish(one);
std::cout << "Expecting to have the tower demolished: ";
std::cout << tower.demolish(two) <<std::endl;
std::cout << "Height of the tower: " << tower.getHeight() <<std::endl;
std::vector<Item> items; //creating an Item vector
items.push_back(Tower(one));
Item items2[1]; //creating an array of Items
items[0]= tower;
std::cout << "Printing out an Item: ";
std::cout << items.back()<<std::endl; //EXPECTING TO GET 2 BUT IT PRINTS NOTHING, WHY IS THAT?
std::cout << "OR: " << items2[0]<<std::endl; //SAME ISSUE HERE, EXPECTING TO GET 3
}
As can be understood from the code, a Card holds an integer value distance and an enum value direction. It would've been a mess if i included that code too. I have commented my questions in the last piece of code test(). Thanks for your help in advance.

std::vector<Item> items; //creating an Item vector
items.push_back(Tower(one));
What happens here is called "slicing". Since you're not storing pointers, but actual objects, the Tower part of the class is just cut off and only the Item part is pushed into the vector. To use virtual functions and polymorphism, you need a reference or pointer to the base class.
std::vector<Item*> items; //creating an Item vector
items.push_back(new Tower(one));
// ...
// at the end of main:
for(int i=0; i < items.size(); ++i)
delete items[i];
Or with smart pointers from Boost or a C++11 library
std::vector<shared_ptr<Item>> items;
items.push_back(make_shared<Tower>(one));
// nothing further needs to be done
For printing, you now obviously need to dereference the pointer:
std::cout << "Printing out an Item: ";
std::cout << *items.back()<<std::endl;
std::cout << "OR: " << *items2[0]<<std::endl;
}

Related

no matching conversion for functional-style cast from 'int' to 'ItemType'

I have a homework assignment in which I have to code some methods for a linked list and test with a driver from the professor. I keep running into this error:
no matching conversion for functional-style cast from 'int' to 'ItemType'
Here are my files for my "Node" class ItemType:
// ItemType.h.
#include <fstream>
const int MAX_ITEMS = 5;
enum RelationType {LESS, GREATER, EQUAL};
class ItemType{
public:
ItemType();
RelationType ComparedTo(ItemType) const;
void Print(std::ostream&) const;
void Initialize(int number);
private: int value;
};
And ItemType.cpp
#include <fstream>
#include <iostream>
#include "ItemType.h"
ItemType::ItemType()
{
value = 0;
}
RelationType ItemType::ComparedTo(ItemType otherItem) const
{
if (value < otherItem.value)
return LESS;
else if (value > otherItem.value)
return GREATER;
else return EQUAL;
}
void ItemType::Initialize(int number)
{
value = number;
}
void ItemType::Print(std::ostream& out) const
// pre: out has been opened.
// post: value has been sent to the stream out.
{
out << value;
}
When I try to use the professors driver, I get an error with initializing the ItemType class with the constructor. I initialize them like so: classList.putItem(ItemType(4))
But I end up with the error stated above, I'm not sure where Im wrong, here is my driver:
#include "unsorted.h"
using namespace std;
int main() {
UnsortedType classList;
classList.PutItem(ItemType(4));
classList.PutItem(ItemType(5));
classList.PutItem(ItemType(4));
classList.PutItem(ItemType(4));
classList.PutItem(ItemType(8));
cout << "(original) length: " << classList.GetLength() << endl; classList.ResetList();
classList.Print();
classList.ShiftRight();
cout << "(shifted right) length: " << classList.GetLength() << endl; classList.ResetList();
classList.Print();
classList.DeleteItem(ItemType(4));
cout << "(delete all 4s) length: " << classList.GetLength() << endl; classList.ResetList();
classList.Print();
classList.ShiftRight();
cout << "(shift right) length: " << classList.GetLength() << endl; classList.ResetList();
classList.Print();
return 0;
}
You don't have a constructor for ItemType that takes an int. A simple fix would be to define that constructor:
ItemType(int v) : value{v} { }

C++ - Updating value in pointer gets overridden

I've recently begun learning C++ and I'm having some trouble updating a pointer in my Movie class. I've got a feeling I have an issue somewhere in my Move/Copy constructors but have been trying to solve this issue for hours, swapping pointers to references to values and finally coming here for help.
I have a class Movie, which contains a string name, string rating and int watched member variables. Another class Movies, holds a vector of the movies. On movie, my method increment_watched is supposed to increment the int watched by one, the value does get incremented but it seems like the value is not saved. The display_all_movies method in Movies, which simply displays the movies that it stores holds the old value for watched. I know the issue is probably something really small but I haven't been able to work out why the value isn't being saved.
If someone could explain why the pointer value seems to be getting overridden I'd appreciate it greatly. Thanks in advance!
Code is below, there is some debug couts in there.
Movie.h
#ifndef _MOVIE_H_
#define _MOVIE_H_
#include <string>
#include <iostream>
class Movie {
private:
std::string *name;
std::string *rating;
int *watched;
public:
std::string get_name();
std::string get_rating();
int get_watched();
void increment_watched();
Movie(std::string name, std::string rating, int watched_val); // normal constructor
Movie(const Movie &source); // copy constructor
Movie(Movie &&source); // move constructor
~Movie();
};
#endif // _MOVIE_H_
Movie.cpp
#include "Movie.h"
std::string Movie::get_name() {
return *name;
}
std::string Movie::get_rating() {
return *rating;
}
int Movie::get_watched() {
return *watched;
}
void Movie::increment_watched() {
std::cout << *watched << std::endl;
(*watched)++; // TODO FIX!
std::cout << *watched << std::endl;
}
Movie::Movie(std::string name, std::string rating, int watched_val)
: name{nullptr}, rating{nullptr}, watched{nullptr}{
std::cout << "Creating movie " << watched_val << " with normal constructor" << std::endl;
this->name = new std::string{name};
this->rating = new std::string{rating};
this->watched = new int{watched_val};
}
Movie::Movie(const Movie &source)
: Movie(*source.name, *source.rating, *source.watched) {
std::cout << "Creating movie " << *source.watched << " with copy constructor" << std::endl;
}
Movie::Movie(Movie &&source)
: Movie(*source.name, *source.rating, *source.watched) {
std::cout << "Creating movie " << *source.watched << " with move constructor" << std::endl;
source.name = nullptr;
source.rating = nullptr;
source.watched = nullptr;
}
Movie::~Movie() {
delete name;
delete rating;
delete watched;
}
Movies.h
#ifndef _MOVIES_H_
#define _MOVIES_H_
#include <vector>
#include <string>
#include <iostream>
#include "Movie.h"
class Movies {
private:
static int count;
std::vector<Movie> *movies;
public:
void add_movie(std::string &&name, std::string &&rating, int &&watch);
void increment_movie_count(std::string &&name);
void display_all_movies();
void count_movies();
Movies();
Movies(const Movie &source); // copy constructor
Movies(Movie &&source); // move constructor
~Movies();
};
#endif // _MOVIES_H_
Movies.cpp
#include "Movies.h"
int Movies::count = 0;
void Movies::add_movie(std::string &&name, std::string &&rating, int &&watch) {
bool contains {false};
for(auto movie : *movies) {
if(movie.get_name() == name) {
contains = true;
}
}
if(!contains) {
movies->push_back(Movie{name, rating, watch});
count++;
}
}
void Movies::increment_movie_count(std::string &&name) {
for(auto movie : *movies) {
if(movie.get_name() == name) {
movie.increment_watched();
}
}
}
void Movies::display_all_movies() {
for(auto movie : *movies) {
std::cout << "Title " << movie.get_name() << " Rating " << movie.get_rating() << " Watched " << movie.get_watched() << std::endl;
}
}
void Movies::count_movies() {
std::cout << "There are " << count << " movies " << std::endl;
}
Movies::Movies() {
movies = new std::vector<Movie>{};
}
Movies::~Movies() {
delete movies;
}
And finally main.cpp
#include <iostream>
#include "Movies.h"
using std::cout;
using std::endl;
int main() {
Movies *my_movies;
my_movies = new Movies();
(*my_movies).count_movies();
my_movies->add_movie("Big", "PG-13", 2);
my_movies->increment_movie_count("Big");
my_movies->display_all_movies();
return 0;
}
Changefor(auto movie : *movies) to for(auto& movie : *movies) to update the original movie objects. Otherwise, you're only updating copies of the movie objects.

C2678 being thrown for no apparent reason to me

I am trying to compile this project just to see how I am doing as I go along, but I still have a few more classes to implement that will inherit from Widget for different types. When I compile I keep getting C2678:
Error C2678 binary '==': no operator found which takes a left-hand
operand of type 'Widget' (or there is no acceptable conversion)
Assignment10 c:\program files (x86)\microsoft visual
studio\2017\community\vc\tools\msvc\14.11.25503\include\xutility line3107
I cant find where this error is thrown or why. Any help would be greatly appreciated. Sorry it's so sloppy, I've been messing with it a lot to try and find the problem.
#pragma once
#include <iostream>
using namespace std;
class Widget
{
public:
int idNumber;
//structors
Widget()
{
idNumber = 0;
}
Widget(int a)
{
idNumber = a;
}
~Widget();
//operations
int getId()
{
return idNumber;
}
//overload operators to compare idNumber
void operator= (Widget &rhs)
{
idNumber = rhs.idNumber;
}
};
----------------------------------------
#include "Widget.h"
#include <iostream>
using namespace std;
Widget::~Widget()
{
}
/*
bool Widget::operator< (Widget &rhs)
{
bool result;
result = idNumber < rhs.idNumber;
return result;
}*/
---------------------------------
#pragma once
#include "Widget.h"
#include <list>
#include <iostream>
using namespace std;
class Inventory
{
public:
Inventory();
Inventory(int i)
{
Widget w(i);
}
~Inventory();
//operations
//process order for shipment
void order(int widgID);
//recieve widget
void receive(int widgID);
//overlaod output operator
friend ostream& operator<<(ostream&, const Widget&);
protected:
list<Widget> onHand;
list<int> onOrder;
};
-------------------------------
#include "Inventory.h"
#include "Widget.h"
#include <iostream>
#include <list>
using namespace std;
Inventory::Inventory()
{
Widget w;
}
Inventory::~Inventory()
{
}
//recieve widget
void Inventory::receive(int widgID)
{
cout << " Recieved shipment of Widget type "
<< widgID << endl;
//find the iterator of the widget location
list<int>::iterator weNeed;
weNeed = find(onOrder.begin(), onOrder.end(), widgID);
//if end is returned, item not found
if (weNeed != onOrder.end())
{
cout << "Ship " << Widget(widgID) << " to fill back order" << endl;
onOrder.erase(weNeed);
}
else
{
onHand.push_front(Widget(widgID));
}
}
//process order
void Inventory::order(int widgID)
{
cout << " Recieved order for Widget type "
<< widgID << endl;
//find the iterator of the widget location
list<Widget>::iterator weHave;
weHave = find(onHand.begin(), onHand.end(), widgID);
//if end is returned, item not found
if (weHave != onHand.end())
{
cout << "Ship " << *weHave << endl;
onHand.erase(weHave);
}
else
{
cout << "Back order widget of type "
<< widgID << endl;
onHand.push_front(Widget(widgID));
}
}
ostream& operator<<(ostream& os, const Widget& wid)
{
os << wid.idNumber;
return os;
}

Data placed into array correctly but is not there when array is printed

I'm implementing my own hash table and I am running into the following problem: when I insert my node(s) into the table, they are not printed out when I loop through the array. I am using an array of arrays as the underlying data structure and the logic is as follows:
I pass my node to an insert function. This function, based on the
type of data in my node, calls the appropriate hash function provided
by the C++ STL.
Then, I mod the hash value returned by the size of
my hash table and use that to determine which array to place the
node.
I also have an array of arrays of booleans (the same size as my
hash table) that I use to check whether a specific spot in my hash
table already has data in it.
If it does, I simply keep looping till
an empty spot is found.
Like I said before, the problem is that the data is inputed correctly into the array (I've checked that with print statements), but when I print the array, nothing is outputted. I have also checked if my object is being constructed correctly (again, with print statements), but everything is looking fine. I've included the full code below. Any help would be greatly appreciated!
///////START OF NODE.H///////////
#ifndef NODE_H
#define NODE_H
#include <iostream>
template <typename T>
class HashTable;
template <typename T>
class Node
{
friend class HashTable<T>;
private:
T data;
public:
Node(T Data): data(Data)
{
std::cout << "In the node constructor" << std::endl;
}
Node()
{
decltype(data) {};
}
T getData() const
{
return data;
}
};
#endif
//////////////////////END OF NODE.H////////////////////
/////START OF HASHTABLE.H///////
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include "Node.h"
#include <iostream>
#include <array>
#include <functional>
#include <typeinfo>
#include <string>
const int TABLE_SIZE=5;
template <typename T>
class HashTable
{
private:
std::array<std::array<Node<T>, TABLE_SIZE>, TABLE_SIZE> hashTable;
std::array<std::array<bool, TABLE_SIZE>, TABLE_SIZE> spots;
public:
HashTable()
{
for(int index=0;index<spots.size();++index)
{
for(int position=0;position<spots.at(index).size();++position)
{
spots.at(index).at(position)=false;
}
}
}
int hashFunction(Node<T> Node)
{
auto key=Node.getData();
std::hash<decltype(Node.getData())> hash_function {};
int hash=hash_function(key);
if(hash < 0)
{
hash*=-1;
}
//std::cout << "The hash value return by the STL hash function for the key " << key << " is " << hash << std::endl;
if(hash > TABLE_SIZE)
{
hash%=TABLE_SIZE;
}
std::cout << "The hash value for the key " << key << " is " << hash << std::endl;
return hash;
}
void insert(Node<T> Node)
{
int hashValue=hashFunction(Node);
auto location=hashTable.at(hashValue);
std::cout << "Going to insert " << Node.getData() << std::endl;
for(int index=0;index<location.size();++index)
{
if(spots.at(hashValue).at(index)==false)
{
std::cout << "Found a spot that is not taken!" << std::endl;
std::cout << "The size of the data at the spot in the array before we insert is: " << location.at(index).getData().size() << std::endl;
location.at(index)=Node;
std::cout << "The size of the data at the spot in the array after we insert is: " << location.at(index).getData().size() << std::endl;
std::cout << "The data that is in the spot in the array: " << location.at(index).getData() << std::endl;
std::cout << std::endl;
spots.at(hashValue).at(index)=true;
break;
}
}
}
bool contains(Node<T> Node)
{
int hashValue=hashFunction(Node);
auto location=hashTable.at(hashValue);
auto result=find_if(begin(location), end(location), [Node] (const auto & element) {return element.getData()==Node.getData();});
if(result!=end(location))
{
return true;
}
return false;
}
int getSize() const
{
int size {};
for(int index=0;index<hashTable.size();++index)
{
size+=hashTable.at(index).size();
}
return size;
}
void print()
{
std::cout << "In the print function" << std::endl;
for(int index=0;index<hashTable.size();++index)
{
//std::cout << hashTable.at(index).size() << std::endl;
for(int position=0;position<hashTable.at(index).size();++position)
{
std::cout << hashTable.at(index).at(position).getData().size() << std::endl;
}
}
/*
for(int index=0;index<spots.size();++index)
{
for(int position=0;position<spots.at(index).size();++position)
{
if(spots.at(index).at(position)==true)
{
std::cout << "There should be some data here" << std::endl;
}
}
}
*/
}
};
#endif
////////////END OF HASHTABLE.H//////////
////////////START OF MAIN.CPP///////////
#include "HashTable.h"
#include <cstdlib>
#include <random>
#include <algorithm>
using namespace std;
int main()
{
HashTable<string> hash_table;
hash_table.insert(Node<string>("Java"));
hash_table.insert(Node<string>("C++"));
hash_table.insert(Node<string>("C#"));
hash_table.insert(Node<string>("Latex"));
hash_table.insert(Node<string>("Python"));
}
/////////////END OF MAIN.CPP/////////////
One error is in your insert(Node<T> Node) function on these line:
auto location=hashTable.at(hashValue);
//...
location.at(index) = Node;
The location should be a reference not a copy. What is happening is that you're making changes to a local location, and not the actual location that the hash table uses. Thus none of your changes "stick".
The line above should be this:
auto& location=hashTable.at(hashValue); // <-- note that auto is a reference
//...
location.at(index) = Node;
Now you are assigning the returned reference to a reference.
Also, I highly recommend you use a debugger, as this error could have been easily diagnosed if you stepped through your code to see what was being done.
in HashTable::insert this line:
auto location = hashTable.at(hashValue);
makes a copy of a Node. You then operate on and store in the copy, not the node in hashTable. Taking a reference to the node
auto & location = hashTable.at(hashValue);
should fix it.

debugging error at the end of the console

I'm a student and I studying c++.
This is my cpp code
int _tmain(int argc, _TCHAR* argv[])
{
CFood output;
output.whatFunc();
cout<<"my outputs"<<endl<<output<<endl;
return 0;
}
ostream& operator <<(ostream& outputStream, const CFood& output)
{
for(int i=0; i<2; i++)
{
outputStream <<"1 : "<<output.m_strName[i]<<" 2 : "<<output.m_servingSize[i]<<"g "<<"3 : "<<
output.m_calorie[i]<<"cal "<<"4 : "<<output.m_transFat[i]<<"g"<<endl;
}
return outputStream;
}
When I debug it, It work. But the end of the console, it gives me error message;;;
It says "An unhandled win32 exception occurred in work.exe [5796]"
My header filed is
class CFood
{
public:
CFood(void);
~CFood(void);
private:
string m_strName[7];
double m_servingSize[7];
double m_calorie[7];
double m_transFat[7];
public:
void whatFunc(void);
friend ostream& operator <<(ostream& outputStream,const CFood& output);
}
I think there is something wrong in my code..And I think it's CFood output;(Just thinking..)
Do you know why it has debug error?
++Sorry, I forgot the whatFunc(void)
This is code
void CFood::whatFunc(void) //
{
m_strName[0]="chicken";
m_strName[1]="rice";
m_strName[2]="meat";
m_strName[3]="strawberry";
m_strName[4]="apple";
m_strName[5]="water";
m_strName[6]="juice";
m_servingSize[0]=10;
m_servingSize[1]=20;
m_servingSize[2]=30;
m_servingSize[3]=40;
m_servingSize[4]=50;
m_servingSize[5]=60;
m_servingSize[6]=70;
m_calorie[0]=10.45;
m_calorie[1]=20.57;
m_calorie[2]=30.78;
m_calorie[3]=40.23;
m_calorie[4]=50.85;
m_calorie[5]=60.73;
m_calorie[6]=70.27;
m_transFat[0]=0.01;
m_transFat[1]=0.02;
m_transFat[2]=0.03;
m_transFat[3]=0.04;
m_transFat[4]=0.05;
m_transFat[5]=0.06;
m_transFat[6]=0.07;
}
Well its difficult to tell what exactly goes wrong without full source code. In my humble opinion, entire source lefts much to be desired. Placing obviously linked data in the bunch of the unlinked arrays with static size is not a very good pattern. Instead try something like that:
#include <iostream>
#include <vector>
#include <string>
#include <ostream>
struct CFoodItem{
std::string m_strName;
double m_servingSize;
double m_calorie;
double m_transFat;
};
class CFood
{
public:
void AddFoodItem(const CFoodItem& cItem);
friend std::ostream& operator <<(std::ostream& outputStream, const CFood& output);
private:
std::vector<CFoodItem> m_vItems;
};
std::ostream& operator <<(std::ostream& outputStream, const CFood& output)
{
for (auto i = output.m_vItems.begin(); i != output.m_vItems.end(); ++i)
{
outputStream << "1 : " << i->m_strName << " 2 : " << i->m_servingSize << "g " << "3 : " <<
i->m_calorie << "cal " << "4 : " << i->m_transFat << "g" << std::endl;
}
return (outputStream);
}
void CFood::AddFoodItem(const CFoodItem& cItem)
{
m_vItems.push_back(cItem);
}
int __cdecl main(void)
{
CFood output;
CFoodItem itm;
itm.m_strName = "some food";
itm.m_servingSize = 100500;
itm.m_calorie = 42;
itm.m_transFat = 42;
output.AddFoodItem(itm);
std::cout << "my outputs" << std::endl << output << std::endl;
return 0;
}