C++ namespaces, inner classes and operator resolution - c++

In the C++ namespace myspace I have a class Outer which in turn has an inner class Inner. While I can declare and define a global friend operator QDataStream& operator<<(QDataStream& s, const myspace::Outer& o), I cannot see how to declare a global friend operator QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& o). The commented out lines represent a failed attempt. I do not see how to declare the inner class without defining the outer.
namespace myspace {
class Outer;
//class Outer::Inner;
}
QDataStream& operator<<(QDataStream& s, const myspace::Outer& o);
//QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& o);
namespace myspace {
class Outer {
friend QDataStream& (::operator <<)(QDataStream&, const Outer&);
class Inner {
//friend QDataStream& (::operator <<)(QDataStream&, const Inner&);
int i;
};
int o;
};
}
I have read
Namespaces and operator resolution, C++ Defining the << operator of an inner class, Accessing private class in operator<< in namespace
and Operator overloading, name resolution and namespaces, but none seem to work.
If I uncomment these lines, the first gives the error message "outer.h:7: error: 'Inner' in 'class myspace::Outer' does not name a type
class Outer::Inner;
^"
This seems to be the key. I cannot declare the inner class.
I am using C++ 11.
This question is not a duplicate of Forward declaration of nested types/classes in C++ if it can can be solved without forward reference.

Given the time lapse, I am posting the correct answer given by Andreas H.
namespace myspace {
class Outer {
class Inner {
friend QDataStream& operator<<(QDataStream&, const Inner&);
int i;
};
friend QDataStream& operator<<(QDataStream&, const Outer&);
friend QDataStream& operator<<(QDataStream&, const Inner&);
int o;
};
QDataStream& operator<<(QDataStream& s, const myspace::Outer& o) {
s << o.o;
return s;
}
QDataStream& operator<<(QDataStream& s, const myspace::Outer::Inner& i) {
s << i.i;
return s;
}
}

Related

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.

cannot access private members in friend ostream

I tried to make friend ostream function. The compiler say i cannot access private member of the class, even though i declared it as friend. I read a similar question and it say the problem is with the namespcaes.(the question: C++ friend function can't access private members)
My Code is below:
header:
#include <iostream>
#include <string>
//using namespace std;
namespace biumath
{
#ifndef BIUMATH_H
#define BIUMATH_H
class Assignment
{
private:
int **m_varArray;
int m_rowsOfVarArray;
public:
Assignment(); //1
Assignment(char symbol, double value); //2
bool containsValueFor(char symbol) const; //3
double valueOf(char symbol) const; //4
void add(char symbol, double val); //5
friend std::ostream& operator<< (std::ostream& out,
const Assignment& assignment);
};
}
#endif
cpp:
#include <iostream>
#include "biumath.h"
using namespace biumath;
using std::cout;
using std::endl;
ostream& operator<< (ostream& out,
const Assignment& assignment){
out<<assignment.m_rowsOfVarArray<<std::endl;
//return the stream. cout print the stream result.
return out;
}
or better yet, avoid all unnecessary friendships by deferring to a public utility method (this also has benefits when your Assignment is a polymorphic base class):
in header file:
namespace biumath
{
class Assignment
{
private:
int **m_varArray;
int m_rowsOfVarArray;
public:
Assignment(); //1
Assignment(char symbol, double value); //2
bool containsValueFor(char symbol) const; //3
double valueOf(char symbol) const; //4
void add(char symbol, double val); //5
void write(std::ostream& os) const; // <=== public helper
};
// free function overload which defers to helper.
// NOTE: it's in the biumath namespace so ADL will find it
inline std::ostream& operator<< (std::ostream& out,
const Assignment& assignment){
assignment.write(out);
return out;
}
}
in CPP file:
namespace biumath {
void Assignment::write(std::ostream& os) const {
os << m_rowsOfVarArray << std::endl;
}
}
You may define the operator in the enclosing namespace (in your case in the global namespace) but you have to use the qualified name.
Thus define the operator like
ostream& biumath::operator<< (ostream& out,
const Assignment& assignment){
out<<assignment.m_rowsOfVarArray<<std::endl;
//return the stream. cout print the stream result.
return out;
}
Only you also have at first to declare the operator in the same namespace where the class is defined.
If you want that the operator would be declared in the global namespace then you can do it the following way
namespace biumath
{
class Assignment;
}
std::ostream& operator<< ( std::ostream &,
const biumath::Assignment & );
namespace biumath
{
class Assignment
{
//...
friend std::ostream& ::operator<< (std::ostream& out,
const Assignment& assignment);
};
}
You've befriended an operator in your biumath namespace, but you don't define that; instead you define a separate operator in the global namespace.
Re-open the namespace in the source file, and put the definition inside it.

friend not getting the private members

I've a class called Packet That I want to serialize with QDataStream I overloaded operator>> and operator<< and in the over loaded function I called stream << somIntMember Though Its declared as friend its complaining for Private Variables
error: 'int DG::Packet::_state' is private
error: 'DG::Packet::PacketType DG::Packet::_type' is private
Here goes my Header.
namespace DG{
class Packet{
public:
struct CommonHeader{
public:
quint32 id;
QTime time;
quint32 size;
PacketType packetType;
public:
CommonHeader();
CommonHeader(quint32 sz, PacketType type);
friend QDataStream& operator<<(QDataStream&, const Packet::CommonHeader& header);
friend QDataStream& operator>>(QDataStream&, Packet::CommonHeader& header);
};
private:
PacketType _type;
int _state;
public:
friend QDataStream& operator<<(QDataStream&, const Packet& packet);
friend QDataStream& operator>>(QDataStream&, Packet& packet);
};
}
And here goes the Ciode
#include "packet.h"
using namespace DG;
QDataStream& operator<<(QDataStream& stream, const Packet& packet){
stream << packet._state << packet._type;
return packet.serialize(stream);
}
Well, the reason for the no match for 'operator>>' error is
that there isn't any match for the operator>>, at least not in
the code you've shown. The only operator>> and operator<<
in the code you've shown are for Packet::CommonHeader and for
Packet. Nothing for a quint32, nor for a QTime, nor for
a PacketType, nor for an int.
For that matter, the implementations you've shown us are for
Packet::CommonHeader and Packet; the classes, however, are
in namespace DG, and not in the global namespace.
That could also explain the reason why friend isn't working.
The operators you've declared as friend are in namespace DG,
those you define are in the global namespace (and are thus
completely unrelated functions).
First remove the const from the rhs parameters of in the >> operators as you are modifying them.

operator<< for nested class

I'm trying to overload the << operator for the nested class ArticleIterator.
// ...
class ArticleContainer {
public:
class ArticleIterator {
// ...
friend ostream& operator<<(ostream& out, const ArticleIterator& artit);
};
// ...
};
If I define operator<< like I usually do, I get a compiler error.
friend ostream& operator<<(ostream& out, const ArticleContainer::ArticleIterator& artit) {
The error is 'friend' used outside of class. How do I fix this?
You don't put the friend keyword when defining the function, only when declaring it.
struct A
{
struct B
{
friend std::ostream& operator<<(std::ostream& os, const B& b);
};
};
std::ostream& operator<<(std::ostream& os, const A::B& b)
{
return os << "b";
}
You must declare it as a friend inside the class, then define it outside the class without the friend keyword.
class ArticleContainer {
public:
class ArticleIterator {
// ...
friend ostream& operator<<(ostream& out, const ArticleIterator& artit);
};
};
// No 'friend' keyword
ostream& operator<<(ostream& out, const ArticleIterator& artit);
the friend keyword is used in the declaration to specify that this func/class is a friend. In the definition outside the class you may not use that keyword. Just remove it