C++ Trying to add >> Operator Overload To Template - c++

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.

Related

c++ | << operator overloading and printing a string

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

Is it possible to get private variable value using class instance name?

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;
}

When using templates, how do I fix the following compiler error to achieve the desired behavior of my program?

I'm practicing templates in Visual Studio 2013 from a not so well written C++ book and I receive the following compiler errors respectively, "error C4430: missing type specifier - int assumed. Note: C++ does not support default-int" and "error C2143: syntax error : missing ',' before '<'".
Both refer me to line 10 which is...
std::ostream& operator<< (std::ostream&, const Array<T>&);
The desired behavior of my code is to show the creation and destruction of temporary Animal objects using templates.
The troubleshooting steps I have tried so far include substituting std::iostream& with int in my return type and first parameter type of line 10. After doing so the error messages remained the same. This seemed to suggest that the problem may be the second parameter type. I then added the keyword typename to the second parameter of my overloading operator function (operator<<) on line 10 and the error still persisted.
Line 10 can be found in the header file below.
//Array.h
#ifndef ARRAY_H
#define ARRAY_H
#include <iostream>
#include "Animal.h"
const int DefaultSize = 3;
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
template <typename T> // declare the template and the paramenter
class Array // the class being parameterized
{
public:
Array(int itsSize = DefaultSize);
Array(const Array &rhs);
~Array() { delete[] pType; }
// operators
Array& operator=(const Array&);
T& operator[](int offSet) { return pType[offSet]; }
const T& operator[](int offSet) const { return pType[offSet]; }
// accessors
int GetSize() const { return itsSize; }
// friend function
friend std::ostream& operator<< (std::ostream&, const Array<T>&);
private:
T *pType;
int itsSize;
};
template <typename T>
Array<T>::Array(int size = DefaultSize) :itsSize(size)
{
pType = new T[size];
for (int i = 0; i < size; i++)
pType[i] = static_cast<T>(0);
}
Array<Animal>::Array(int AnimalArraySize) :itsSize(AnimalArraySize)
{
pType = new Animal[AnimalArraySize];
}
template <typename T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.GetSzie();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
}
template <typename T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if (this == &rhs)
return *this;
delete[] pType;
itsSize = rhs.GetSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
return *this;
}
template <typename T>
std::ostream& operator<< (std::ostream& output, const Array<T> &theArray)
{
for (int i = 0; i < theArray.GetSize(); i++)
output << "[" << i << "]" << theArray[i] << std::endl;
return output;
}
#endif
Here's the rest of my code from my book for your reference.
//Animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
#include <iostream>
class Animal
{
public:
// constructors
Animal();
Animal(int);
~Animal();
// accessors
int GetWeight() const { return itsWeight; }
void SetWeight(int theWeight) { itsWeight = theWeight; }
// friend operators
friend std::ostream& operator<<(std::ostream&, const Animal&);
private:
int itsWeight;
};
#endif
//Animal.cpp
#include "Animal.h"
#include <iostream>
Animal::Animal() :itsWeight(0)
{
std::cout << "animal() ";
}
Animal::Animal(int weight) : itsWeight(weight)
{
std::cout << "animal(int) ";
}
Animal::~Animal()
{
std::cout << "Destroyed an animal...";
}
//Main.cpp
#include <iostream>
#include "Animal.h"
#include "Array.h"
std::ostream& operator<<(std::ostream&, const Animal&);
void IntFillFunction(Array<int>& theArray);
void AnimalFillFunction(Array<Animal>& theArray);
int main()
{
Array<int> intArray;
Array<Animal> animalArray;
IntFillFunction(intArray);
AnimalFillFunction(animalArray);
std::cout << "intArray...\n" << intArray;
std::cout << "\nanimalArray...\n" << animalArray << std::endl;
std::cin.get();
return 0;
}
std::ostream& operator<<(std::ostream& theStream, const Animal& theAnimal)
{
theStream << theAnimal.GetWeight();
return theStream;
}
void IntFillFunction(Array<int>& theArray)
{
bool Stop = false;
int offset, value;
while (!Stop)
{
std::cout << "Enter an offset (0-9) and a value. ";
std::cout << "(-1 to stop): ";
std::cin >> offset >> value;
if (offset < 0)
break;
if (offset > 9)
{
std::cout << "***Please use values between 0 and 9.***\n";
continue;
}
theArray[offset] = value;
}
}
void AnimalFillFunction(Array<Animal>& theArray)
{
Animal *pAnimal;
for (int i = 0; i < theArray.GetSize(); i++)
{
pAnimal = new Animal(i * 10);
theArray[i] = *pAnimal;
delete pAnimal;
}
}
I've tried my best to keep this question on topic by providing you with the desired behavior of the program, a specific problem or error and the shortest code necessary to reproduce it. All of which are requirements for debugging help as documented in the Help Center page.
I'm new to this website, and if my question is still off-topic, please let me know how I can change my question to be more on topic or inform me of a better place to ask my question. - Thank you
This function is declared before the Array class is declared (i.e., the compiler has never seen that type and doesn't know what it is, hence your error).
template<typename> class Array; // Add this forward declaration
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
Edit
I just noticed that the operator<< is declared before the Array class and as a friend function within the Array class. You could just remove the declaration at the top.
Edit 2
Array.h
I removed the following items
#include "Animal.h"
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
Array<Animal>::Array(int AnimalArraySize) :itsSize(AnimalArraySize)
{
pType = new Animal[AnimalArraySize];
}
Updated the friend function declartion to be
template<typename T> // This is not a member function so must be declared as a template
friend std::ostream& operator<< (std::ostream&, const Array<T>&);
Animal.h
This class has the friend function but it's not implemented in the cpp file. I moved the definition from the main.cpp into Animal.cpp

output operator overloading for queue class C++

I am trying to overload the << operator in order to print objects of classes, I tried making a friend function of the operator and then declaring it in below the Queue class, I have not written anything inside the code block here is what I have, it wont compile, it will crash instantly, thanks in advance.
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class Employee{
protected:
long empId;
string empName;
string email;
public:
Employee(){}
Employee(long i, string n){
empName = n,
empId =i;
email = "Unknown";
}
};
class Student{
protected:
long stId;
int year;
string email;
string schoolName;
public:
Student(){}
Student(long i, int y, string sn){
stId = i;
year =y;
email = "Unknown";
schoolName=sn;
}
};
template<class T>
class Queue{
protected:
vector<T> theQ;
public:
void Push(T item);
T pop();
void ReadAnItem();
void PrintQ();
**template<T>** edit
friend ostream& operator<< (ostream& is, const Queue<T>& theQ);
};
template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ){
**os << theQ.Print();** Edit
return os;
}
template<class T>
void Queue<T>::ReadAnItem(){
T item;
cout << "Enter the data please: " << endl;
cin >> item;
Push(item);
}
template<class T>
void Queue<T>::Push(T item){
theQ.front() = item;
}
template<class T>
void Queue<T>::PrintQ(){
cout << "The content of the array is as follows: " << endl;
for (int i=0; i< theQ.size(); i++){
cout << theQ[i] << **endl;** I get an "invalid overload of endl"
}
}
You should declare that friend function as a template:
template <class U>
friend ostream& operator<< (ostream& is, const Queue<U>& theQ);
Your operator<< function is a template function, so note that inside friend declaration:
friend ostream& operator<< <T>(ostream& is, const Queue<T>& theQ);
This is not the as Andy's variant, as Andy's variant allows this:
#include <iostream>
template <class T>
class A
{
public:
A(T d): data(d){}
private:
// friend is any template instance of function foo, and not just foo<T>!
template <class U>
friend void foo(A<U>& t);
T data;
};
A<int> ai(1);
template <class T>
void foo(A<T>& t)
{
// A<int> will accept foo<double> as friend
std::cout << ai.data << std::endl;
std::cout << t.data << std::endl;
}
int main()
{
A<double> ad(2);
foo(ad);
return 0;
}
However, in my case, you need to add few forward declarations, in order to make this right:
#include <iostream>
// 2. But before that you need to forward-declare your class, so the function
// can know about the class.
template <class T>
class A;
// 1. You need to forward-declare your foo function...
template <class T>
void foo(A<T>& t);
template <class T>
class A
{
public:
A(T d): data(d){}
private:
friend void foo<T>(A<T>& t);
T data;
};
A<int> ai(1);
template <class T>
void foo(A<T>& t)
{
// error: ‘int A<int>::data’ is private within this context
//std::cout << ai.data << std::endl;
std::cout << t.data << std::endl;
}
int main()
{
A<double> ad(2);
foo(ad);
}
Here's your code, but you need more work to do:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class Employee{
protected:
long empId;
string empName;
string email;
public:
Employee(){}
Employee(long i, string n){
empName = n,
empId =i;
email = "Unknown";
}
};
class Student{
protected:
long stId;
int year;
string email;
string schoolName;
public:
Student(){}
Student(long i, int y, string sn){
stId = i;
year =y;
email = "Unknown";
schoolName=sn;
}
};
template<class T>
class Queue;
template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ);
template<class T>
class Queue{
protected:
vector<T> theQ;
public:
void Push(T item);
T pop();
void ReadAnItem();
void PrintQ() const;
friend ostream& operator<< <T> (ostream& is, const Queue<T>& theQ);
};
template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ){
// I will just use this, but it should receive ostream
theQ.PrintQ();
return os;
}
template<class T>
void Queue<T>::ReadAnItem(){
T item;
cout << "Enter the data please: " << endl;
cin >> item;
Push(item);
}
template<class T>
void Queue<T>::Push(T item){
// this aint gonna work! Use std::deque and push_front! theQ.front() = item;
}
template<class T>
void Queue<T>::PrintQ() const{
cout << "The content of the array is as follows: " << endl;
for (int i=0; i< theQ.size(); i++){
// You need to overlload operator<< for student to make this work! cout << theQ[i] << endl;
}
}
int main()
{
Queue<Student> s;
s.Push(Student());
std::cout << s;
return 0;
}
Note - this code is not perfect (nor good), it just shows you how to solve this particular problem. You need to move body of PrintQ() method to operator<< or to make your PrintQ to accept and return ostream&. Also, I've already marked it as a const, as it doesn't change state of the class. Also, you don't have operator<< for student, so you are not able to output it into the ostream&. Also, vector.first() = s will always wipe your first element (it will copy s into the first element of the vector using operator=), or it will fail, if there's no first element. I'm sure there's other bugs, but these are only that I saw while trying your program.
Edit
For each different class, you need to have different operator<<. So, change the Student to:
class Student{
protected:
long stId;
int year;
string email;
string schoolName;
friend ostream& operator<<(ostream& os, const Student& s);
public:
Student(){}
Student(long i, int y, string sn){
stId = i;
year =y;
email = "Unknown";
schoolName=sn;
}
};
and add another operator<< body:
ostream& operator<<(ostream& os, const Student& s)
{
os << s.stId << s.year << s.email << std::endl;
return os;
}
Also, do this for Employee. And you should consider moving common fields from Student and Employee to base class Person.

C++ equivalent of Java's toString?

I'd like to control what is written to a stream, i.e. cout, for an object of a custom class. Is that possible in C++? In Java you could override the toString() method for similar purpose.
In C++ you can overload operator<< for ostream and your custom class:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
This way you can output instances of your class on streams:
A x = ...;
std::cout << x << std::endl;
In case your operator<< wants to print out internals of class A and really needs access to its private and protected members you could also declare it as a friend function:
class A {
private:
friend std::ostream& operator<<(std::ostream&, const A&);
int j;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.j << ")";
}
You can also do it this way, allowing polymorphism:
class Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Base: " << b << "; ";
}
private:
int b;
};
class Derived : public Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Derived: " << d << "; ";
}
private:
int d;
}
std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }
In C++11, to_string is finally added to the standard.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
As an extension to what John said, if you want to extract the string representation and store it in a std::string do this:
#include <sstream>
// ...
// Suppose a class A
A a;
std::stringstream sstream;
sstream << a;
std::string s = sstream.str(); // or you could use sstream >> s but that would skip out whitespace
std::stringstream is located in the <sstream> header.
The question has been answered. But I wanted to add a concrete example.
class Point{
public:
Point(int theX, int theY) :x(theX), y(theY)
{}
// Print the object
friend ostream& operator <<(ostream& outputStream, const Point& p);
private:
int x;
int y;
};
ostream& operator <<(ostream& outputStream, const Point& p){
int posX = p.x;
int posY = p.y;
outputStream << "x="<<posX<<","<<"y="<<posY;
return outputStream;
}
This example requires understanding operator overload.