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.
Related
I have written simple class like below in file VRKVector.h
namespace vrk {
class VRKVector {
private:
std::vector<int> m_coordinates;
int m_dimension;
public:
/** VRKVector constructor.
* #param coordinates which represents a vector coordinates.
* #return none.
*/
VRKVector(std::vector<int> coordinates);
/** operator << : output stream operator
* #param out which is output stream we want to write
* #param vector which represents a vector coordinates.
* #return none.
*/
friend std::ostream& operator << (std::ostream& out, vrk::VRKVector& vrkvector);
};
}
VRKVector.cpp
// ============================================================================
// Local includes, e.g. files in the same folder, typically corresponding declarations.
#include "VRKVector.h"
// ============================================================================
// System includes, e.g. STL.
#include <iostream>
#include <fstream>
#include <sstream>
#include <iterator>
#include <algorithm>
// namespace declarations;
using namespace std;
using namespace vrk;
VRKVector::VRKVector(std::vector<int> coordinates) {
m_coordinates = coordinates;
m_dimension = coordinates.size();
}
std::ostream& operator<< (std::ostream& out, vrk::VRKVector& vrkvector) {
out << vrkvector.m_dimension;
return out; // return std::ostream so we can chain calls to operator<<
}
Above code I am getting error as shown below
1>C:\VRKVector.cpp(42,18): error C2248: 'vrk::VRKVector::m_dimension': cannot access private member declared in class 'vrk::VRKVector'
1>C:\\VRKVector.h(40): message : see declaration of 'vrk::VRKVector::m_dimension'
We can assess private member as we have friend function. Why am I seeing the error?
You need to define the operator<< in the namespace vrk, the friend declaration declares it as the member of the namespace vrk.
A name first declared in a friend declaration within a class or class template X becomes a member of the innermost enclosing namespace of X, ...
std::ostream& vrk::operator<< (std::ostream& out, vrk::VRKVector& vrkvector) {
// ^^^^^
out << vrkvector.m_dimension;
return out; // return std::ostream so we can chain calls to operator<<
}
std::ostream& operator<< (std::ostream& out, vrk::VRKVector& vrkvector){}
Is not the definition of
friend std::ostream &operator<<(std::ostream &out, vrk::VRKVector &vrkvector);
As it's in a different namespace, it can't access the private class member as is to be expected, a global function can't access a given class private members.
You can fix it by using one of the following options:
Defining it inline:
friend std::ostream &operator<<(std::ostream &out, vrk::VRKVector &vrkvector){
out << vrkvector.m_dimension;
return out; // return std::ostream so we can chain calls to operator<<
}
Defining it inside the namespace.
Using namespace scope:
std::ostream& vrk::operator<< (std::ostream& out, vrk::VRKVector& vrkvector) {
/*...*/
}
I'm trying to overload the << operator for a class that's part of a user-defined namespace. What's interesting is that if I remove all that namespace stuff, the program compiles and runs without a problem, but the fact that the class resides in a namespace somehow makes the compilation process for the file A.cpp fail with an error saying that I'm trying to access private data in class A (demo.cpp compiles fine). Please, take a look at my three-file program and the compilation error that I get:
demo.cpp:
#include <iostream>
#include "A.h"
int main() {
usr::A a(4);
std::cout << a << std::endl;
return 0;
}
A.h:
#ifndef A_H_
#define A_H_
#include <iostream>
namespace usr {
class A {
private:
int m_x;
public:
A(int x);
friend std::ostream& operator<<(std::ostream& os, const usr::A& a);
};
}
#endif // A_H_
A.cpp:
#include "A.h"
usr::A::A(int x) : m_x(x) {}
std::ostream& operator<<(std::ostream& os, const usr::A& a) {
os << a.m_x;
return os;
}
Error:
$ g++ -c A.cpp
In file included from A.cpp:1:0:
A.h: In function ‘std::ostream& operator<<(std::ostream&, const usr::A&)’:
A.h:10:17: error: ‘int usr::A::m_x’ is private
int m_x;
^
A.cpp:7:13: error: within this context
os << a.m_x;
^
Non-qualified friend declarations always refer to members of the smallest enclosing namespace. When a class is declared in namespace usr, any non-qualified friend declaration inside that class refers to members of usr. I.e. your friend declaration declared usr::operator << as a friend.
The global ::operator << remains a non-friend in this case, which is why you get the error when you attempt to access private members of usr::A from ::operator <<.
If you want this to work, you have to either
Make your operator << a member of usr, or
Make sure the friend declaration explicitly refers to global operator << by using a qualified name ::operator << (this will also require introducing ::operator << before trying to refer to it by its qualified name).
I would suggest the first approach. If your class A is a member of namespace usr, then it is a good idea to declare all functions that handle A as members of usr as well. This will help you to avoid many problems with argument-dependent lookup (ADL) down the road.
But if for some reason you need your operator << to remain a member of global namespace, then here are the hoops you'd have to jump through to make it compile (combined into a single translation unit)
// Pre-declare `usr::A` to enable pre-declaration of our `::operator <<`
namespace usr {
class A;
}
// Pre-declare our `::operator <<`
std::ostream& operator<<(std::ostream& os, const usr::A& a);
namespace usr {
class A {
private:
int m_x;
public:
A(int x);
friend std::ostream& ::operator<<(std::ostream& os, const usr::A& a);
// Friend declaration uses qualified name - it explicitly
// refers to `::operator <<` declared above
};
}
usr::A::A(int x) : m_x(x) {}
std::ostream& operator<<(std::ostream& os, const usr::A& a) {
os << a.m_x;
return os;
}
int main() {
usr::A a(4);
std::cout << a << std::endl;
}
Under GCC you have to separate return-type and scope resolution operator (:: token) via some access modifier (reference on const or pointer).
For example, this will not compile under g++7.2.0:
std::string f(int a);
namespace NS
{
class C
{
friend std::string ::f(int a);
// scope operator ^^ is absolutely needed
}
}
But this will:
std::string f(int a);
namespace NS
{
class C
{
friend std::string const ::f(int a);
// see const keyword ^
}
}
And this will:
std::string f(int a);
namespace NS
{
class C
{
friend std::string& ::f(int a);
// see ref symbol ^
}
}
Considering the following code:
namespace myNS {
class MyClass {
//.....
};
} //end of namespace myNS
using namespace myNS;
//overloading of '<<' operator
std::ostream &myNS::operator<<(std::ostream &os, MyClass &c){ /*....*/ }
In the last line, why is &myNS:: needed?
& is needed because, conventionally, streaming operators return a reference to the stream to allow them to be chained:
stream << something << something_else;
with something_else being passed to the stream reference returned by stream << something.
myNS:: is needed if this operator is supposed to be scoped inside the namespace, in which case there must also be a previous declaration inside the namespace. If you want the operator to be in the current namespace (presumably the global namespace in this example), then it's not needed.
Since std::ostream& operator<<(std::ostream&, MyClass&) is not declared inside the myNS namespace, there is no need to qualify it. This equivalent code is legal:
#include <iostream>
namespace Foo
{
class Bar{};
}
using namespace Foo;
std::ostream& operator<<(std::ostream& o, const Bar&) { return o;}
int main()
{
Foo::Bar b;
std::cout << b << "\n";
}
Problem Solved, thank you all for your help!
I've run into a problem that i can't seem to figure out.
I am trying to overload the ostream operator as a friend function in order to be able to print out the member data of that object, and i can't seem to get it to work.
This is what i got so far:
.h file:
Class TestIt:
{
public:
TestIt();
TestIt(int a, b);
friend ostream& operator <<(ostream& outputStream, const TestIt& a);
Private:
int NUMBER1;
int NUMBER2;
};
.cpp file:
ostream& operator <<(ostream& outputStream, const TestIt& a)
{
outputStream << a.NUMBER1 << " " << a.NUMBER2;
return(outputStream);
}
What i am trying to do is, pass in an object in ostream, then output its member data.
The error that i am receiving is that
"the member TestIt::NUMBER1 declared in TestIt.h is inaccessible.
and same error also exists with my other member data.
Why would that be?
Thank you for your help.
Here's a whole program that i just wrote, giving me the same error:
TestClass.cpp
#include "TestClass.h"
#include <iostream>
using namespace std;
TestClass::TestClass(int a, int b)
{
age = a;
whole = b;
}
int TestClass::GetAge() const
{
return(age);
}
ostream& operator <<(ostream& outputStream, const TestClass& t1)
{
t1.whole;
t1.age;
return(outputStream);
}
TestClass.h
#ifndef TestClass_H
#define TestClass_H
class TestClass
{
public:
TestClass(int a, int b);
int GetAge() const;
friend ostream& operator <<(ostream& outputStream, const TestClass& t1);
private:
int whole;
int age;
#endif
The operator<< that you've defined and the operator<< that you've friended aren't the same name. Are you using namespaces?
I'm trying to write a class that overloads the insertion operator but in my header file I get the error.
Overloaded 'operator<<' must be a binary operator (has 3 parameters)
Here is my code:
.h file
ostream & operator<<(ostream & os, Domino dom);
.cpp file
ostream & operator<< (ostream & os, Domino dom) {
return os << dom.toString();
}
I'm following a text book and this is what they use as an example but its not working for me.. Any suggestions?
You probably put your operator<< inside a class declaration. That means it takes an extra hidden parameter (the this parameter). You need to put it outside of any class declaration.
The insertion operator (<<) can be used as a member function or a friend function.
operator << used as a member function
ostream& operator<<(ostream& os);
This function should be invoked as :
dom << cout;
In general if you are using the operator as a member function, the left hand side of the operator should be an object. Then this object is implicitly passed as an argument to the member function. But the invocation confuses the user and it does not look nice.
operator << used as a friend function
friend ostream& operator<<(ostream& os, const Domino& obj);
This function should be invoked as :
cout << dom;
In this case the object dom is explicitly passed as a reference. This invocation is more traditional and user can easily understand the meaning of the code.
/*insertion and extraction overloading*/
#include<iostream>
using namespace std;
class complex
{
int real,imag;
public:
complex()
{
real=0;imag=0;
}
complex(int real,int imag)
{
this->real=real;
this->imag=imag;
}
void setreal(int real)
{
this->real=real;
}
int getreal()
{
return real;
}
void setimag(int imag)
{
this->imag=imag;
}
int getimag()
{
return imag;
}
void display()
{
cout<<real<<"+"<<imag<<"i"<<endl;
}
};//end of complex class
istream & operator >>(istream & in,complex &c)
{
int temp;
in>>temp;
c.setreal(temp);
in>>temp;
c.setimag(temp);
return in;
}
ostream &operator <<(ostream &out,complex &c)
{
out<<c.getreal()<<c.getimag()<<endl;
return out;
}
int main()
{
complex c1;
cin>>c1;
// c1.display();
cout<<c1;
//c1.display();
return 0;
}