I had a class name address:
#ifndef __ADRESS
#define __ADRESS
#include <iostream>
using namespace std;
class Adress
{
private:
std::string street;
int number;
std::string city;
public:
Adress(std::string name = "Hertzel", int number = 1, std::string city = "Tel Aviv"); //C'tor
Adress(const Adress& other); //cpy c'tor
Adress(Adress&& other);//Move c'tor
//Get methods
const string& getStreet() const;
int getNumber() const;
const string& getCity() const;
//Set methods
bool setStreet(std::string streetName);
bool setNumber(int num);
bool setCity(std::string cityName);
const Adress& operator=(const Adress& other);
friend ostream& operator<<(ostream& os, const Adress& adress);
};
#endif // !__ADRESS
The street and city were originally char* and now I changed it to strings.
But now I have a weird issue. While using char* I managed to use operator<< function inorder to print the content of address, now after switching to string instead char* when I try printing an address the program terminates.
This is the implementation I wrote for the function:
ostream& operator<<(ostream& os, const Adress& adress)
{
os << adress.street << " " << adress.number << " " << adress.city;
return os;
}
Is anyone familiar with that problem?
Thanks!
The error appears to be elsewhere. You didn't give any implementation file so I had to fill in a dummy implementation for the setters and I can't reproduce the error.
#ifndef ADDRESS_H
#define ADDRESS_H
#include <ostream>
#include <string>
class Adress{
private:
std::string street;
int number; //can this be negative or zero
std::string city;
public:
~Adress() = default;
Adress() : street("Hertzel"), number(1), city("Tel Aviv"){}
Adress(const Adress& other) = default;
Adress(Adress&& other) = default;
Adress& operator=(const Adress& other) = default;
//Get methods
const std::string& getStreet() const { return street; }
int getNumber() const { return number; }
const std::string& getCity() const{ return city; }
//Set methods
bool setStreet(std::string streetName) {
//check empty, is_alphanum etc
street = streetName;
return true;
}
bool setNumber(int num){
//check zero negative
number = num;
return true;
}
bool setCity(std::string cityName){
//checks here
city = cityName;
return true;
}
friend std::ostream& operator << (std::ostream& os, const Adress& adress);
};
inline std::ostream& operator << (std::ostream& os, const Adress& adress){
os << adress.street << " " << adress.number << " " << adress.city;
return os;
}
#endif
main
#include <iostream>
#include "address.hpp"
int main(int, char**){
Adress a;
std::cout << a << '\n';
}
Compiled with gcc-10 seems fine. Debugger time it appears
Related
I have a class IPrintable which is a template and a class which derives from it - Date. I want to add the operator >> to the template but keep getting an error:
source.cpp(16): error C2259: 'Date': cannot instantiate abstract class
source.cpp(16): note: due to following members:
source.cpp(16): note: 'void IPrintable<Date>::toIs(std::istream &)': is abstract
iprintable.h(19): note: see declaration of 'IPrintable<Date>::toIs'
I have successfully added the << operator to the template this way:
virtual void toOs(ostream& os) const = 0;
friend ostream& operator << (ostream& output, const IPrintable& toPrint) {
toPrint.toOs(output);
return output;
}
And then I have declared virtual void toOs(ostream& os) const = 0; to date.h and implemented it in date.cpp.
This is my IPrintable.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
template <class T>
class IPrintable {
private:
public:
virtual void toOs(ostream& os) const = 0;
friend ostream& operator << (ostream& output, const IPrintable& toPrint) {
toPrint.toOs(output);
return output;
}
virtual void toIs(istream& input) = 0;
friend istream& operator >> (istream& input, IPrintable& toSet) {
toSet.toIs(input);
return input;
}
};
This is the declaration of in Date.h, under public:
virtual void toOs(ostream& output) const;
virtual void toIS(istream& input);
This is the implementation of the << (toOs) and >> (toIs) in Date.cpp:
void Date::toOs(ostream& output) const {
if (!isLeapYear(this->getDay(), this->getMonth(), this->getYear())) {
cout << "Not a leap year";
return;
}
output << getDay() << "/" << getMonth() << "/" << getYear();
}
void Date::toIS(istream& input) {
int index;
string str;
input >> str;
index = str.find('/');
this->setDay(stoi(str.substr(0, index)));
str = str.substr(index + 1);
index = str.find('/');
this->setMonth(stoi(str.substr(0, index)));
str = str.substr(index + 1);
this->setYear(stoi(str));
}
Please, if any more information is needed please let me know and I will do my best to provide it.
Thanks!
Your Date::toIS has a capital S, while your IPrintable::toIs does not. If you add override to the declaration of Date::toIS, you would see that it doesn't actually override anything.
I'm working on a project where I have to write a class that contains three other classes as private member variables to a binary file, where it can then be read back into variables to be used in the code. The code writes to the file, but I don't know if it is writing the correct info as when I try to read the file it reads in junk. I have included my current setup, does this look correct? If so, what could be going wrong, and if not, how can I fix this?
If you need me to add any extra code, please ask. Another consideration is that two of the classes being used as member functions for the players objects inherit from other classes.
if (cFile.is_open())
{
cFile.seekp(ios::beg);
for (int i = 0; i < 3; i++)
{
cFile.write(reinterpret_cast<char *>(&players[i]), sizeof(Character));
}
cFile.seekg(ios::beg);
for (int i = 0; i < 3; i++)
{
cFile.read(reinterpret_cast<char *>(&playersRead[i]), sizeof(Character));
playersRead[i].display();
}
cFile.close();
}
else
{
cout << "Error opening file." << endl;
}
I've been working on this code for a few days and am really having trouble. I appreciate any help I can get, thanks in advance.
#pragma once
#include <iostream>
using std::ostream;
#include "string.h"
#include "coinPouch.h"
#include "backpack.h"
class Character
{
public:
Character();
Character(String name);
Character(String name, CoinPouch wallet, Backpack storage);
Character(const Character & copy);
~Character();
Character & operator =(const Character & rhs);
friend ostream & operator << (ostream & out, const Character & c);
void purchase(int p, int g, int s, int c);
void income(int p, int g, int s, int c);
void addPotion(const Potion & toAdd);
void checkBalance();
void checkBackpack();
void changeName(const String & newN);
void display();
String getName();
CoinPouch getWallet();
Backpack getStorage();
void setName(String name);
void setWallet(CoinPouch wallet);
void setStorage(Backpack storage);
private:
String m_name;
CoinPouch m_wallet;
Backpack m_storage;
};
#include "character.h"
using std::endl;
using std::cout;
Character::Character() : m_name("Player")
{
CoinPouch initialW;
Backpack initialS;
m_wallet = initialW;
m_storage = initialS;
}
Character::Character(String name) : m_name(name)
{
CoinPouch initialW;
Backpack initialS;
m_wallet = initialW;
m_storage = initialS;
}
Character::Character(String name, CoinPouch wallet, Backpack storage) : m_name(name), m_wallet(wallet), m_storage(storage)
{
}
Character::Character(const Character & copy) : m_name(copy.m_name), m_wallet(copy.m_wallet), m_storage(copy.m_storage)
{
}
Character::~Character()
{
}
Character & Character::operator =(const Character & rhs)
{
if (this != &rhs)
{
m_name = rhs.m_name;
m_wallet = rhs.m_wallet;
m_storage = rhs.m_storage;
}
return *this;
}
ostream & operator << (ostream & out, const Character & c)
{
out << c.m_name << ": " << endl;
out << c.m_wallet << endl;
out << c.m_storage << endl;
return out;
}
void Character::purchase(int p, int g, int s, int c)
{
m_wallet.buy(p, g, s, c);
}
void Character::income(int p, int g, int s, int c)
{
m_wallet.add(p, g, s, c);
}
void Character::addPotion(const Potion & toAdd)
{
m_storage.addPotion(toAdd);
}
void Character::checkBalance()
{
m_wallet.display();
}
void Character::checkBackpack()
{
m_storage.displayContents();
}
void Character::changeName(const String & newN)
{
m_name = newN;
}
void Character::display()
{
cout << m_name << ": " << endl;
m_wallet.display();
m_storage.displayContents();
}
String Character::getName()
{
return m_name;
}
CoinPouch Character::getWallet()
{
return m_wallet;
}
Backpack Character::getStorage()
{
return m_storage;
}
void Character::setName(String name)
{
m_name = name;
}
void Character::setWallet(CoinPouch wallet)
{
m_wallet = wallet;
}
void Character::setStorage(Backpack storage)
{
m_storage = storage;
}
#pragma once
#include <iostream>
using std::ostream;
#include "string.h"
class CoinPouch
{
public:
CoinPouch();
CoinPouch(String init);
CoinPouch(int p, int g, int s, int c);
CoinPouch(const CoinPouch & copy);
~CoinPouch();
CoinPouch & operator = (const CoinPouch & rhs);
friend ostream & operator << (ostream & out, const CoinPouch & c);
void add(int p, int g, int s, int c);
bool checkCost(int p, int g, int s, int c);
void buy(int p, int g, int s, int c);
void convertCost();
void roundUp();
void display();
int getP();
int getG();
int getS();
int getC();
private:
String m_amount;
int m_platinum;
int m_gold;
int m_silver;
int m_copper;
};
#pragma once
#include "potions.h"
class DynamicArray
{
public:
// Constructors
DynamicArray();
~DynamicArray();
DynamicArray(const DynamicArray & copy);
// Op Equals
DynamicArray & operator =(const DynamicArray & rhs);
// Insert, delete, and get elements functions
int getElements();
void Insert(const Potion & add);
void Delete(const Potion & rmv);
void display();
// Overloaded operators
Potion & operator [](int index);
friend ostream & operator << (ostream & out, const DynamicArray & d);
private:
// Member variables
Potion * m_array;
int m_elements;
// Find function
int Find(const Potion & target);
};
#pragma once
#include "string.h"
#include <iostream>
using std::ostream;
class Potion
{
public:
// Constructors
Potion();
Potion(String name, String description, String potency, String cost);
Potion & operator = (const Potion & rhs);
Potion(const Potion & copy);
// Desctructor
~Potion();
// Overloaded operators
bool operator == (const Potion & rhs) const;
friend ostream & operator << (ostream & out, const Potion & p);
// Getter functions
String getName();
String getDesc();
String getPotency();
String getCost();
int getP();
int getG();
int getS();
int getC();
// Setter functions
void setName(String name);
void setDesc(String desc);
void setPotency(String potency);
void setCost(String cost);
// Convert and display functions
void convertCost();
void display();
private:
// Strings to hold item information
String m_name;
String m_description;
String m_potency;
String m_cost;
// Ints to hold cost information
int m_platinum;
int m_gold;
int m_silver;
int m_copper;
// Logical test
bool m_isnull = false;
};
#pragma once
#include <iostream>
using std::ostream;
class String
{
public:
// Constructors
String();
String(char ch);
String(const char * str);
// Destructor
~String();
// Copy Constructor and Copy Assignment Constructor
String(const String & copy);
String & operator=(const String & rhs);
friend ostream & operator << (ostream & out, const String & s);
// Added Functionality
void display();
void upper();
void lower();
// Operator Conversion
operator char *();
operator const char *();
// Overloaded operator
bool operator == (const String & rhs) const;
private:
// Member variables
char * m_str;
int m_ischar;
};
#pragma once
#include "dynamicarray.h"
#include "coinPouch.h"
#include "string.h"
class Backpack
{
public:
Backpack();
Backpack(DynamicArray potions);
Backpack(const Backpack & copy);
~Backpack();
Backpack & operator = (const Backpack & rhs);
friend ostream & operator << (ostream & out, const Backpack & c);
void addPotion(const Potion & add);
void usePotion(const Potion & rm);
void displayContents();
private:
DynamicArray m_potions;
int m_number;
};
This is a school project, and I am supposed to write the Character class to a binary file in order to save the characters so I can load them in on the program start. Right now I'm just trying to make sure that they can be successfully written to and read from the binary file and I have had no luck.
My bad, didn't know what to post and I didn't want to post everything in my file. Here is the character class. Let me know what else is needed, if anything.
It should be immediately obvious that this code can't possibly work.
cFile.write(reinterpret_cast<char *>(&players[i]), sizeof(Character));
However big sizeof(Character) is, we could have a Character with an m_name that takes up more bytes than that. So this code can't possibly be writing the character's name, and it clearly needs to do that.
Before you write anything to a file, decide on (and ideally, document) a file format at the byte level. Make sure your code writes in the format you documented and also can read in the format you documented. Skipping this step leads to pain and it also makes debugging impossible because you can't look at the file and compare it to a specification to see whether the writer or the reader is at fault.
Had you documented what bytes the player's name will occupy in the file, you'd immediately realize that you either need to have a variable-length object and encode the length somehow or pick a largest size name and allocate those many bytes. But because you skipped that vital step, you never actually worked out how to write a Character to a file.
Say I have a Person class with a field string name. Now let's have a class Student deriving Person with a field int avgGrade. Both classes have the operator<< defined.
I want to be able to store in an array or similar structure elements of type Person, but also be able to store derived class objects in it. I'll be later traversing the elements and want to use the operator<< and actually call that specific object's definition for that operator, instead of always the base version of it.
How would I go about doing that? In what structure and what kind type of elements should I store?
Here's the current collection of classes:
Person.h:
#pragma once
#include <iostream>
class Person
{
private:
std::string name;
public:
Person();
Person(std::string);
friend std::ostream& operator<<(std::ostream& os, const Person& obj);
}
Person.cpp:
#include "Person.h"
Person::Person() : Person("default") { }
Person::Person(std::string name)
{
this->name = name;
}
std::ostream& operator<<(std::ostream& os, const Person& obj)
{
os << "Name: " << obj.name;
return os;
}
Student.h:
#pragma once
#include "Person.h"
#include <iostream>
class Student : Person
{
private:
double avgGrade;
public:
Student();
Student(const std::string cs, const double avg_grade);
friend std::ostream& operator<<(std::ostream& os, const Student& obj);
};
Student.cpp:
#include "Student.h"
Student::Student() : Student("default", 4) { }
Student::Student(const std::string cs, const double avg_grade)
: Person(cs),
avgGrade(avg_grade)
{
this->avgGrade = avg_grade;
}
std::ostream& operator<<(std::ostream& os, const Student& obj)
{
os << (Person)obj << std::endl;
os << "Average grade: " << obj.avgGrade;
return os;
}
Demo.cpp:
#include "Person.h"
#include "Student.h"
#include <iostream>
int main(int argc, char* argv[])
{
Person p("john");
Student s("johana", 5);
Person* arr[2];
arr[0] = &p;
arr[1] = &s; // Error: conversion to inaccessible base class "Person" is not allowed
std::cout << arr[0] << std::endl;
std::cout << arr[1] << std::endl;
return 0;
}
The general solution to this sort of problem is to declare:
inline std::ostream& operator<<(std::ostream& str, const Base& o)
{
o.print(str);
return str;
}
as a non-member function, then:
virtual void print(std::ostream& str);
in Base, and override in Derived as required. (The Derived version may well start with Base::print(str); to call the base version.)
Your declaration of array is fine, but you would then print the elements with:
std::cout << *arr[0] << std::endl;
std::cout << *arr[1] << std::endl;
The problem with initializing the array, is that by default, base classes are private. Fix that with:
class Student : public Person ...
For example, I've written a class called Length:
class Length {
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
void print(float value) {
std::cout << value;
}
void computeStuff(float value) {
//do the computing
}
int main() {
Length width;
width.setValue(5);
std::cout << width; // <-- this is actually just an example
//what I actually want is:
print(width); // print 5
//or perhaps even
computeStuff(width);
return 0;
}
Now how to make width return value_ or 5?
Technically, width is not an instance name, it's a name of a variable of type Length. You can change your code to retrieve a variable in two ways:
Add a friend operator << for Length that does the printing, or
Add an implicit conversion operator from Length to float.
The first approach works only for output. You cannot pull the value directly:
friend ostream& operator <<(ostream& out, const Length& len) {
out << len.value_;
return out;
}
The second approach looks like this:
class Length {
...
public:
operator float() const { return value_; }
};
You must overload operator<< for your custom type, something like:
class Length
{
..
friend std::ostream& operator<<(std::ostream& os, const Length& o);
..
}
std::ostream& operator<<(std::ostream& os, const Length& o)
{
os << o.value_;
return os;
}
Mind that this
must be non member
is nothing special , just an operator overload applied to a standard way of inserting things into stream of <iostream>
You need to define an operator() method to print the value 5.
You need to overload the << operator for your class. You could also use a function to do the operator's work.
Operator <<
#include <iostream>
class Length {
friend std::ostream& operator<<(std::ostream& os, const Length& l);
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
std::ostream& operator<<(std::ostream& os, const Length& l)
{
os << l.value_;
return os;
}
int main() {
Length width;
width.setValue(5);
std::cout << width << std::endl; // print 5
return 0;
}
function:
#include <iostream>
class Length {
friend std::ostream& print(std::ostream &,const Length &l);
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
std::ostream& print(std::ostream &os, const Length &l)
{
os << l.value_;
return os;
}
int main() {
Length width;
width.setValue(5);
print(std::cout, width) << std::endl;
return 0;
}
Suppose this is my class:
class Student {
std::string name;
int CWID;
public:
Student(std::string name = "N/A", int CWID = 99999999) : this->name(name), this->CWID(CWID) {}
};
Now, how do I overload the output stream operator << that will print all the data in the class. I'm guessing this is equivalent to the toString() method in Java but kindly show me how to do it in C++.
Add member functions to the class that return the name and CWID.
std::string getName() const {return name;}
int getCWID() const {return CWID;}
Then, add a non-member function to write the data out to a stream.
std::ostream& operator<<(std::ostream& out, Student const& s)
{
return out << s.getName() << " " << s.getCWID();
}
Here is how you do it:
class Student {
std::string name;
int CWID;
public:
Student(std::string name = "N/A", int CWID = 99999999) : name(name), CWID(CWID) {}
friend std::ostream& operator<<(std::ostream& stream, const Student& student);
};
std::ostream& operator<<(std::ostream& stream, const Student& student)
{
stream << '(' << student.name << ", " << student.CWID << ')';
return stream;
}
Please note that this overloaded function is not part of the class.
You could write non-member function
std::ostream& operator<<(std::ostream& os, const Student& stud)
{
os << stud.name << " " << stud.CWID;
return os;
}
and declare it as friend function in your class
class Student {
std::string name;
int CWID;
public:
Student(std::string name = "N/A", int CWID = 99999999) : this->name(name), this->CWID(CWID) {}
friend ostream& operator<<(ostream& os, const Student& stud);
};