How to overload ostream operator<< for a pimpl class? - c++

This is what I tried so far:
class Fahrzeug
{
public:
std::string Id() const;
void Id(const std::string &id);
friend std::ostream& operator<< (std::ostream &out, const Fahrzeug &fzg)
{
out << Id();
return out;
}
private:
struct DatenImpl;
boost::scoped_ptr<DatenImpl> _datenImpl;
};
This yields a compiler error:
error C2352: Id() - illegal call of non-static member function
How can I implement the ostream operator<< for a "pimpled" class?

Your definition should be:
friend std::ostream& operator<< (std::ostream &out, const Fahrzeug &fzg)
{
out << fzg.Id(); // <--- qualify call to Id()
return out;
}
The operator is not a class member, although defined inside the class.

Related

How to define the friend operator<< for a private class member in a .cpp file, and not in a header?

Compilation of this code fails:
class P {
//public:
class C {
friend std::ostream& operator<<(std::ostream &os, const C &c);
};
};
std::ostream& operator<<(std::ostream &os, const P::C &c) {
return os;
}
error:
test.cpp:12:53: error: 'C' is a private member of 'P'
std::ostream& operator<<(std::ostream &os, const P::C &c) {
^
test.cpp:6:9: note: implicitly declared private here
class C {
^
1 error generated.
Uncommenting public: makes this code to compile. And it obviously can be moved to the class itself.
But what is the correct way to define such operator<< in a cpp file for a private member class?
To see the private elements of P , your operator<< must be friend of P. So in order to be able to access the definition of class C:
class P {
class C {
...
};
friend std::ostream& operator<<(std::ostream &os, const C &c);
};
Then, your current operator will compile. But it can only access public members of C, since it is a friend of the enclosing P but not of the nested C:
std::ostream& operator<<(std::ostream &os, const P::C &c) {
return os;
}
If you also need to access private members of C you need to be double friend:
class P {
class C {
int x; //private
friend std::ostream& operator<<(std::ostream &os, const C &c); // to access private x
};
friend std::ostream& operator<<(std::ostream &os, const C &c); // to access private C
};
std::ostream& operator<<(std::ostream &os, const P::C &c) {
os<<c.x;
return os;
}

Friend function can no longer access private data members of class after class is encapsulated in namespace

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) {
...
}

friend keyword for operator overloading

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.

Overriding ofstream operator<<

Why i still have ERROR: exepected an identifier in std::ofstream << val on the line below? msvc.
std::ostream& operator<< (bool val) { m_lock.lock(); std::ofstream << val; m_lock.unlock(); return *this; }
class OfstreamLog : public std::ofstream {
private:
std::mutex m_lock;
public:
OfstreamLog() : std::ofstream() { }
explicit OfstreamLog(const char* filename, ios_base::openmode mode = ios_base::out) : std::ofstream(filename, mode) { }
std::ostream& operator<< (bool val) { m_lock.lock(); std::ofstream << val; m_lock.unlock(); return *this; }
std::ostream& operator<< (short val);
std::ostream& operator<< (unsigned short val);
std::ostream& operator<< (int val);
std::ostream& operator<< (unsigned int val);
std::ostream& operator<< (long val);
std::ostream& operator<< (unsigned long val);
std::ostream& operator<< (float val);
std::ostream& operator<< (double val);
std::ostream& operator<< (long double val);
std::ostream& operator<< (void* val);
std::ostream& operator<< (std::streambuf* sb);
std::ostream& operator<< (std::ostream& (*pf)(std::ostream&));
std::ostream& operator<< (std::ios& (*pf)(std::ios&));
std::ostream& operator<< (ios_base& (*pf)(ios_base&));
};
std::ofstream is a type name. You can't call a nonstatic method or operator for it without any object.
In this case you probably want std::ofstream::operator<<(val); instead of std::ofstream << val;.
Explanation:
When you want to call method of a parent class from method of a child class, you do it like this:
class A
{
void func() {}
};
class B
{
void test()
{
func(); // Like this
}
};
But if child class have method with same name (more precisely, with same signature (it means, same name and argument types)), it will be called instead of parent's one. To explicitly call the method of the parent class, you can use this syntax:
class A {...};
class B
{
void test()
{
A::func(); // Notice `A::`
}
};
Now let's talk about operators. When you want to call an operator, you usually use an object name for it, like object << 10;. But when you want to call operator of a class (or it's parent) from a method of this class, you should use full operator syntax:
class A
{
operator<<(int){}
};
class B
{
void test()
{
operator<<(10); // <-----
*this << 10; // Also you can do it like this
}
};
Now, we combine these two techniques:
If child class have operator with same signature as parent's one and you want to call operator of the parent, you do it like this:
class A {...};
class B
{
void test()
{
A::operator<<(10); // Notice `A::`
*(A*)this << 10; // Also you can do it like this
}
};

Operator << and inheritance/composition

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