Reputation: 5
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!
Upvotes: 0
Views: 333
Reputation: 69892
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;
}
Upvotes: 0
Reputation: 29724
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.
Upvotes: 2
Reputation: 12627
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;
}
Upvotes: 1
Reputation: 8805
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);
};
Upvotes: 1
Reputation: 42909
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.
Upvotes: 1