I've found myself in a bit of trouble trying to overload operator<< correctly. I've searched around other questions about it, but none of the answers seemed to fit this one, so here it is:
I have a class (Register) that stores specimens of another class(subclasses of Film, which is abstract). The overloaded operator << for Register should put all the data stored in each Film type element on screen through the ostream class.Here's the code:
class Register{
private:
int elementNum;
Film* pData;
};
ostream &operator<<(ostream & os,const Register &v);
These are in the header, operator << in the cpp:
ostream &operator<<(ostream & os,const Register &v){
for(int i=0;i<v.elementNum;i++){
os<<v.pData[i].print()<<endl;
}
return os;
}
Problem is, this way i cannot access the private variables of Register. So I tried putting the overaloaded operator<< as a member of Register, but then the compiler tells me the function must take only one argument. Last, if I remove ostream& os from the parameters, it tells me the function needs two arguments. So i would be interested in a solution where the information stored in pData can be put on screen efficiently with operator <<. Thanks in advance!
You have to declare operator<< as a friend if access to Register implementation (private data) has to be granted:
class Register{
private:
//...
friend std::ostream &operator<<( std::ostream & os,const Register &v);
};
std::ostream &operator<<( std::ostream & os,const Register &v) {
for( int i=0; i<v.elementNum; i++){
os << v.pData[i].print() << std::endl;
}
return os;
}
Friend function has access to all private ( as well as protected and public) data of a class that declared a friend.
C++ Standard n3337 § 11.3/1 says
Friends
A friend of a class is a function or class that is given permission to
use the private and protected member names from the class. A class
specifies its friends, if any, by way of friend declarations. Such
declarations give special access rights to the friends, but they do
not make the nominated friends members of the befriending class.
§ 11.3/2
Declaring a class to be a friend implies that the names of private and
protected members from the class granting friendship can be accessed
in the base-specifiers and member declarations of the befriended
class.
Make your operator<< a friend of the class. You can read it up here.
You could make operator<< a friend of class Register see code below:
class Register{
private:
friend ostream &operator<<(ostream & os,const Register &v);
int elementNum;
Film* pData;
};
Thus, operator<< will have access to class Register private members.
To access the private members of Register, make operator<< a friend function:
class Register{
private:
int elementNum;
Film* pData;
friend ostream &operator<<(ostream & os,const Register &v);
};
I implemented the OS-Operator in a project like this:
XYZ.h file
friend std::ostream& operator<<(std::ostream& os, const Liwanze& arg);
XYZ.cpp file
std::ostream& operator<<(std::ostream& os, const Liwanze& arg) {
string area = "";
if (arg.loc == 1)
area = "Buxtehude";
if (arg.loc == 2)
area = "Bangladesch";
if (arg.loc == 3)
area = "Zimbabwe";
if (arg.loc == 4)
area = "Bronx";
os << arg.name << " [" << area << "] ";
return os;
}
or if you wish to avoid polluting your class with unwanted friends, defer the formatting to a public member of Register.
class Register{
public:
void writeTo(std::ostream& os) const {
for( int i=0; i<elementNum; i++){
os << pData[i].print() << std::endl;
}
}
private:
//...
};
std::ostream &operator<<( std::ostream & os,const Register &v) {
v.writeTo(os);
return os;
}
If you make the writeTo function defer to a protected virtual function, then operator<< will work on anything derived from Register, even in a multi-threaded environment.
class Register{
public:
// public non-polymorphic interface...
void writeTo(std::ostream& os) const {
os << "any header information\n" << endl;
std::lock_guard<std::mutex> myLock(_myInternalMutex); // in MT environment
handleWriteTo(os); // defer to protected polymorphic implementation
}
protected:
virtual void handleWriteTo(std::ostream& os) const {
for( int i=0; i<elementNum; i++){
os << pData[i].print() << std::endl;
}
}
private:
//...
};
std::ostream &operator<<( std::ostream & os,const Register &v) {
v.writeTo(os);
return os;
}
Related
I have a class called Circle that I encapsulated inside a namespace.
namespace my_name_space {
class Circle;
}
class my_name_space::Circle {
private:
double radius;
public:
friend std::ostream& operator << (std::ostream &os, const Circle &c);
};
Here is the function in the implementation file:
std::ostream& operator << (std::ostream &os, const Circle &c)
{
os << "Radius: " << c.radius;
return os;
}
Before encapsulating the class within the namespace, everything was working fine. Now the friend function can no longer access the private data members. I don't understand what's wrong.
When you declare operator << as the friend of Circle, it'll become the member of the innermost enclosing namespace of Circle. That means when you put Circle into namespace my_name_space, operator << becomes the member of namespace my_name_space too. The definiton of operator<< doesn't match that, it defines operator<< at globle scope.
A name first declared in a friend declaration within class or class template X becomes a member of the innermost enclosing namespace of X
You can move the definition of operator<< into namespace my_name_space:
namespace my_name_space {
std::ostream& operator << (std::ostream &os, const Circle &c) {
...
}
}
Or if you still want to keep operator<< at global scope:
// delcaration
std::ostream& operator << (std::ostream &os, const my_name_space::Circle &c);
class my_name_space::Circle {
...
friend std::ostream& ::operator << (std::ostream &os, const Circle &c);
// ~~
};
// definition
std::ostream& operator << (std::ostream &os, const my_name_space::Circle &c) {
...
}
I tried to write an simple example for the <<-operator-overloading.
Before, i've never used the keyword "friend". But it does not work without it. What is the mistake i did or why do i need the friend keyword here?
class rational{
public:
rational(double num, double count)
: n(num),c(count){}
rational& operator+=(const rational& b){
this->n+= b.n;
this->c+= b.c;
return *this;
}
friend std::ostream& operator<<(std::ostream& os, const rational& obj)
{
std::cout << obj.n << "," << obj.c << std::endl;
return os;
}
private:
double n;
double c;
};
Thanks
You didn't make any mistake. The friend keyword gives your operator<<() implementation access to private (and protected, if you had any) members of your class.
Note that because it's a friend, operator<<() here is implicitly a free function and not a member function (if it were a member function, it could access private things already!). Because it's declared and defined only inside the class, it can only be found by argument-dependent lookup, but this is fine for operator<< and is a detail you don't have to worry about yet.
You want to stream objects whose internals are not accessible through their class' public interface, so the operator can't get at them. Then you have two choices: Either put a public member into the class which does the streaming
class T {
public:
void stream_to(std::ostream& os) const {os << obj.data_;}
private:
int data_;
};
and call that from the operator:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
obj.stream_to(os);
return os;
}
or make the operator a friend
class T {
public:
friend std::ostream& operator<<(std::ostream&, const T&);
private:
int data_;
};
so that it can access the class' private parts:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
os << obj.data_;
return os;
}
You are declaring and defining the operator inside the class, thus without friend it has an implicit first operand of type rational. You wouldn't have such problem if you had declared the operator outside the class, but then you wouldn't have access to n and c.
I have the following class template which will accept both primitives and object. However like this I can only print primitives. How can I make it function using both primitives and objects? Thanks
template<class T>
class A
{
private:
vector <T> l;
public:
void print() const
{
for (int i=0;i<.size();i++)
{
cout<<l[i]<<endl; //error here
}
}
};
The reason why you can print primitives is that <iostream> provides overloads for operator<< for them.
To let your template print your classes in the same way, you need to define your own implementation of the operator:
// This implementation puts operator << outside your class.
// Mark it "friend" in MyClass if it needs access to private members of MyClass.
ostream& operator<<(ostream& ostr, const MyClass& myClass) {
// Do the printing based on the members of your class
ostr << myClass.member1 << ":" << myClass.member2;
return ostr;
}
The compiler will detect this operator during template expansion, and use it for printing when you do this:
cout<<l[i]<<endl;
You can put operator<< inside your class as well:
ostream &operator<<(ostream &os) {
ostr << member1 << ":" << member2;
}
I am assuming that here, you want to print an object instead of a variable belonging to a fundamental datatype.
For such cases, you can look at operator overloading in C++(more specifically overloading insertion operator).
For more information about overloading the insertion operator for an object, you can visit this URL
http://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx
Given below is an example about how to go about it
ostream& operator<<(ostream& os, const Datatype& dt)
{
os << dt.a <<" " << dt.b;
return os;
}
Here Datatype is the name of the class and a and b are two private members of a and b which will be printed when you try to print the object.
However, to overload using this technique, do not forget to make this function as a friend function of the class(as given below) as the function requires access the to private members of the class.
friend ostream& operator<<(ostream& os, const Datatype& dt);
Code snippet from lexical_cast:
class lexical_castable {
public:
lexical_castable() {};
lexical_castable(const std::string s) : s_(s) {};
friend std::ostream operator<<
(std::ostream& o, const lexical_castable& le);
friend std::istream operator>>
(std::istream& i, lexical_castable& le);
private:
virtual void print_(std::ostream& o) const {
o << s_ <<"\n";
}
virtual void read_(std::istream& i) const {
i >> s_;
}
std::string s_;
};
std::ostream operator<<(std::ostream& o,
const lexical_castable& le) {
le.print_(o);
return o;
}
std::istream operator>>(std::istream& i, lexical_castable& le) {
le.read_(i);
return i;
}
Based on document,
template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
1> Returns the result of streaming arg into a standard library
string-based stream and then out as a Target object.
2> Source is OutputStreamable
3> Target is InputStreamable
Question1> For User Defined Type (UDT), should the OutputStreamable or InputStreamable always have to deal with std::string? For example, given a class containing a simple integer as member variable, when we define the operator<< and operator>>, what is the implementation code looks like? Do I have to convert the integer as a string? Based on my understanding, it seems that UDT always has to deal with std::string in order to work with boost::lexical_cast and boost::lexcial_cast needs the intermediate std::string to do the real conversion jobs.
Question2> Why the return value of operator<< or operator>> in above code is not reference to std::ostream& or std::istream& respectively?
To make your class usable with lexical_cast, just define the "stream" operators for it.
From Boost.LexicalCast Synopsis:
Source is OutputStreamable, meaning that an operator<< is defined that takes a std::ostream or std::wostream object on the left hand side and an instance of the argument type on the right.
Target is InputStreamable, meaning that an operator>> is defined that takes a std::istream or std::wistream object on the left hand side and an instance of the result type on the right.
Target is CopyConstructible [20.1.3].
Target is DefaultConstructible, meaning that it is possible to default-initialize an object of that type [8.5, 20.1.4].
:
// either inline friend, out-of-class friend, or just normal free function
// depending on whether it needs to access internel members
// or can cope with the public interface
// (use only one version)
class MyClass{
int _i;
public:
// inline version
friend std::ostream& operator<<(std::ostream& os, MyClass const& ms){
return os << ms._i;
}
// or out-of-class friend (friend declaration inside class only)
friend std::ostream& operator<<(std::ostream& os, MyClass const& ms);
// for the free function version
int get_i() const{ return _i; }
};
// out-of-class continued
std::ostream& operator<<(std::ostream& os, MyClass const& ms){
return os << ms._i;
}
// free function, non-friend
std::ostream& operator<<(std::ostream& os, MyClass const& ms){
return os << ms.get_i();
}
The same of course for operator>>.
How do I overload the << operator? From the error I am getting, it seems that std::cout doesn't know how to use <<.
This is in a class:
// uint64_t UPPER, LOWER;
std::ostream & operator<<(std::ostream & stream){
if (UPPER)
stream << UPPER;
stream << LOWER;
return stream;
}
I am getting error: no match for 'operator<<' in 'std::cout << test' which doesn't seem to make sense.
edit:
Neither this:
std::ostream & operator<<(std::ostream & stream, uint128_t const & val){
if (val.upper())
stream << val.upper();
stream << val.lower();
return stream;
}
nor this:
std::ostream & operator<<(std::ostream & stream, uint128_t val){
if (val.upper())
stream << val.upper();
stream << val.lower();
return stream;
}
is changing the error.
The << operator takes two arguments, a left hand side, and a right hand side. Therefore you have to define the function with two parameters:
std::ostream operator<<(std::ostream &os, const MyClass &obj);
And you have to define it outside of your class definition, as far as I can remember. Inside of the class definition you can only have operators that take that class as the left hand side.
You typically want the operator<<() overload to be a 'free function' (outside of your class) so it can bind to the stream naturally:
// this is outside your class definition
std::ostream& operator<<(std::ostream& os, const myclass& rhs)
{
// whatever...
return os;
}
Then inside your class you declare it a friend if necessary so it can get to the class internals:
friend std::ostream& operator<<(std::ostream& os, const myclass& rhs);
An alternative to having this be a friend (which some people consider to be breaking encapsulation) is to have a public function in your class that will output itself to a stream and call that in your operator<<() overload:
// inside class myclass - a normal public member function
std::ostream& dump( std::ostream& os)
{
os << some_class_member;
// ...
return os;
}
// now, the `operator<<()` overload doesn't need to be a friend
// this is still outside your class definition
std::ostream& operator<<(std::ostream& os, const myclass& rhs)
{
return rhs.dump(os);
}
operator<< outside a class requires two arguments:
std::ostream& operator<<(std::ostream& stream, type_you_want_output const& thing)