I'm writing a basic overload of the << operator so I've added a friend function inside the class interface
namespace Warehouse
{
namespace Dto
{
class Product;
class AbstractOrder : public ICloneableItem
{
protected:
unsigned long _id;
std::string _name;
std::vector<Product*> _products;
public:
AbstractOrder();
virtual ~AbstractOrder();
double computePrice() const;
void addProduct(Product* product);
void removeProduct(Product* product);
void removeAllProducts();
void setName(const std::string& name) { _name = name; }
std::string getName() const { return _name; }
unsigned long getId() const { return _id; }
std::vector<Product*> getProductList() const { return _products; }
friend std::ostream& operator<<(std::ostream& os, const AbstractOrder& ord);
};
}
}
Inside the implementation file this is the code of the function
using namespace Warehouse::Dto;
....
std::ostream& operator<<(std::ostream& os, const AbstractOrder& ord)
{
os << "[" << ord._id << "] Order " << ord._name << ": " << ord.computePrice();
return os;
}
Why I'm getting the following error?
Error 1 error C2248: 'Warehouse::Dto::AbstractOrder::_id' : cannot access protected member declared in class 'Warehouse::Dto::AbstractOrder'
Actually I've already fixed it,prepending the namespace before the operator<< on the implementation file.
What I don't understand is why I have to do it even if in the implementation file I've used a using namespace Warehouse::Dto directive?
Because the operator << is defined in the global namespace and the AbstractOrder class is defined in the Warehouse::Dto namespace. But the friend declaration is for a stream operator in the Warehouse::Dto namespace.
If you want to defined proper friend declaration for the operator in the global namespace is would be:
friend std::ostream& ::operator<<(std::ostream& os, const AbstractOrder& ord);
But then again you want the operator to live in the same namespace as the class it is streaming.
Related
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 ...
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);
};
So I have an abstract class Product with fields name and price. There are a few classes that inherit from Product, and the reason Product is abstract is because these subclasses have to implement this function (defined in Product):
virtual std::string getCategory()=0;
Category is not a field, it just depends on which subclass we have and in some cases on the price.
Now I want an output operator for the subclasses of Product, but since I only want to print the name and price, I did this in Product.h:
friend std::ostream& operator<<(std::ostream& os, const Product& secondOperand);
And this in Product.cpp:
ostream& operator<<(ostream& outputStream, Product& secondOperand){
outputStream << "["<<secondOperand.getName()<<" "<<secondOperand.getPrice()<<"]"<<endl;
return outputStream;
}
Now I get this error in visual studio:
Error C2259: 'Product' : cannot instantiate abstract class
I don't want to implement this output for every subclass (cause then I have to literally copy everything which isn't ideal). Also, I started out with Product being not pure virtual, but then I had Linker errors for the getCategory() functions...
Nothing wrong with the approach, here's a sample which compiles and runs....
#include <string>
#include <iostream>
using namespace std;
class Product
{
public:
friend std::ostream& operator<<(std::ostream& os, const Product& secondOperand);
virtual ~Product() = 0;
string getName() { return "Product Name"; }
string getPrice() {return "£1.00"; }
virtual std::string getCategory()=0;
};
ostream& operator<<(ostream& outputStream, Product& secondOperand){
outputStream << "["<<secondOperand.getName()<<" "<<secondOperand.getPrice()<<"]"<<endl;
return outputStream;
}
Product::~Product() {}
class DerivedProduct : public Product
{
public:
DerivedProduct() {}
std::string getCategory() { return "Derived getCategory()"; }
};
int main(int argc, char *argv[])
{
DerivedProduct d;
cout << d.getCategory() << endl;
cout << d << endl;
return 0;
}
I was wondering if there is any way to overload the << operator for a class without declaring it as a friend function. My professor said this is the only way to do it, but I wanted to know if there is another way that he was unaware of.
There is no need to make the operator<< function a friend of the class as long as everything you want to be output is accessible through the public interface of the class.
You need to declare it is as friend function if and only if you need access to it's private members.
You can always do this without using friend function if:
1) No private member access is required.
2) You provide a mechanism to access your private member otherwise. e.g.
class foo
{
int myValue;
public:
int getValue()
{
return myValue;
}
}
Yes, you can
std::ostream& operator<<(std::ostream &stream, WHATEVER_TYPE var) {
std::string str = somehowstringify(var);
return stream << str;
}
Note however that by virtue of it being a non-member non-friend function it can of course only access the public interface of std::ostream, this usually isn't a problem.
Yes, one way to do it is like this:
class Node
{
public:
// other parts of the class here
std::ostream& put(std::ostream& out) const { return out << n; };
private:
int n;
};
std::ostream& operator<<(std::ostream& out, const Node& node) {
return node.put(out);
}
As R Sahu has pointed out, the requirement is that the operator should be able to access everything it has to display.
Here are a few possible options
1.Adding the overloaded function as a friend function
2.Making all the required data members of the class accessible for the function using either public accessor methods or public data members
class MyClass {
private:
int a;
int b;
int c;
public:
MyClass(int x,int y,int z):a(x),b(y),c(z) {};
MyClass():a(0),b(0),c(0) {};
int geta() { return a; }
int getb() { return b; }
int getc() { return c; }
};
std::ostream& operator<<(std::ostream &ostr,MyClass &myclass) {
ostr << myclass.geta()<<" - " << myclass.getb() << " - " << myclass.getc() ;
return ostr;
}
int main (int argc, char const* argv[])
{
MyClass A(4,5,6);
cout << A <<endl;
return 0;
}
3.Add a public helper function , say output with the signature std::ostream& output(std::ostream& str) and use it later in the operator function.
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.