Overloading Insertion Operator in C++ - c++

I have a class in which I'm trying to overload the << operator. For some reason, it is not being overloaded.
Here is my .h file:
friend std::ostream& operator<<(std::ostream&, const course &); //course is my class object name
in my .cpp, I have this as my implementation:
std::ostream& operator<<(std::ostream &out, const course & rhs){
out << rhs.info;
return out;
}
This should be correct, but when I try to compile it, it says that cout << tmp; is not defined in ostream.
I've included iostream in my .cpp and .h
I'm been pulling my hair out trying to figure this out. Can you see anything that's wrong with this?
EDIT:
Since what I'm doing seems to be correct, here's all of my source code: http://pastebin.com/f5b523770
line 46 is my prototype
line 377 is the implementation
line 435 is where it fails when i attempt to compile it.
also, I just tried compiling it on another machine, and it gives this error instead:
course.cpp:246: error: non-member function 'std::ostream& operator<<(std::ostream&, const course&)' cannot have cv-qualifier
make: *** [course.o] Error 1

The syntax you've listed is correct, but the overloaded operator prototype has to be declared in the course definition to work properly.
course.h
class course {
public:
friend std::ostream& operator<<(std::ostream&, const course&);
private:
int info;
}
course.cpp
std::ostream& operator<<(std::ostream &out, const course &rhs){
out << rhs.info;
return out;
}

It looks fine to me. Here's my version of it:
course.h
#include <iostream>
class course
{
public:
friend std::ostream& operator<<(std::ostream&, const course &); //course is my class object name
int info;
course(){info = 10;}
};
course.cpp
#include <iostream>
#include "course.h"
std::ostream& operator<<(std::ostream &out, const course & rhs)
{
out << rhs.info;
return out;
}
main_file.cpp
#include <iostream>
#include "course.h"
int main()
{
course a;
std::cout<<a;
return 0;
}

You should include the rest of the code, I don't think we can see where the problem is.
The following trivial example works:
class course
{
public:
course(int info) : info(info) { }
int info;
friend std::ostream& operator<<(std::ostream&, const course &);
};
std::ostream& operator<<(std::ostream &out, const course & rhs)
{
out << rhs.info;
return out;
}
int main(int, char*[])
{
course tmp(3);
std::cout << tmp;
return 0;
}

I found this helpful!
My insertion and extraction operators are slightly different.
here they are defined:
friend ostream& operator<<(ostream &fout, datatype toPrint)
friend istream& operator>>(istream &fin, datatype &toReadTo)
the syntax needs to be exact.

Related

Friend function still can't access private member

I have a simple C++ class, which I'm trying to add stream operators to, so it can be used with cout and cin
#include <iostream>
namespace testing_namespace {
class test {
friend std::ostream &operator<<(std::ostream &os, const test &o);
friend std::istream &operator>>(std::istream &is, test &o);
public:
void doThing();
private:
int member;
};
}
This is the implementation file:
std::ostream &operator<<(std::ostream &os, const testing_namespace::test &o) {
return os << o.member;
}
std::istream &operator>>(std::istream &is, testing_namespace::test &o) {
return is >> o.member;
}
void testing_namespace::test::doThing() {
std::cout << member << " thing" << std::endl;
}
I'm getting an error on compilation:
In function 'std::ostream& operator<<(std::ostream&, const testing_namespace::test&)':
test.cpp:8:20: error: 'int testing_namespace::test::member' is private within this context
return os << o.member;
with a similar error for operator>>. The doThing method compiles with no issues.
I'm not sure what I'm missing here - shouldn't friend functions be able to access the private members of the class test?
You need to define those functions under the namespace too. When you do that, you can omit the name of the namespace from test.
namespace testing_namespace
{
std::ostream &operator<<(std::ostream &os, const test &o) {
return os << o.member;
}
std::istream &operator>>(std::istream &is, test &o) {
return is >> o.member;
}
}

How do I overload << in std::stringstream [duplicate]

I am writing a small matrix library in C++ for matrix operations. However my compiler complains, where before it did not. This code was left on a shelf for 6 months and in between I upgraded my computer from debian etch to lenny (g++ (Debian 4.3.2-1.1) 4.3.2
) however I have the same problem on a Ubuntu system with the same g++.
Here is the relevant part of my matrix class:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
}
}
And the "implementation":
using namespace Math;
std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {
[...]
}
This is the error given by the compiler:
matrix.cpp:459: error: 'std::ostream&
Math::Matrix::operator<<(std::ostream&,
const Math::Matrix&)' must take
exactly one argument
I'm a bit confused by this error, but then again my C++ has gotten a bit rusty after doing lots of Java those 6 months. :-)
Just telling you about one other possibility: I like using friend definitions for that:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
[...]
}
};
}
The function will be automatically targeted into the surrounding namespace Math (even though its definition appears within the scope of that class) but will not be visible unless you call operator<< with a Matrix object which will make argument dependent lookup find that operator definition. That can sometimes help with ambiguous calls, since it's invisible for argument types other than Matrix. When writing its definition, you can also refer directly to names defined in Matrix and to Matrix itself, without qualifying the name with some possibly long prefix and providing template parameters like Math::Matrix<TypeA, N>.
You have declared your function as friend. It's not a member of the class. You should remove Matrix:: from the implementation. friend means that the specified function (which is not a member of the class) can access private member variables. The way you implemented the function is like an instance method for Matrix class which is wrong.
To add to Mehrdad answer ,
namespace Math
{
class Matrix
{
public:
[...]
}
std::ostream& operator<< (std::ostream& stream, const Math::Matrix& matrix);
}
In your implementation
std::ostream& operator<<(std::ostream& stream,
const Math::Matrix& matrix) {
matrix.print(stream); //assuming you define print for matrix
return stream;
}
Assuming that we're talking about overloading operator << for all classes derived from std::ostream to handle the Matrix class (and not overloading << for Matrix class), it makes more sense to declare the overload function outside the Math namespace in the header.
Use a friend function only if the functionality cannot be achieved via the public interfaces.
Matrix.h
namespace Math {
class Matrix {
//...
};
}
std::ostream& operator<<(std::ostream&, const Math::Matrix&);
Note that the operator overload is declared outside the namespace.
Matrix.cpp
using namespace Math;
using namespace std;
ostream& operator<< (ostream& os, const Matrix& obj) {
os << obj.getXYZ() << obj.getABC() << '\n';
return os;
}
On the other hand, if your overload function does need to be made a friend i.e. needs access to private and protected members.
Math.h
namespace Math {
class Matrix {
public:
friend std::ostream& operator<<(std::ostream&, const Matrix&);
};
}
You need to enclose the function definition with a namespace block instead of just using namespace Math;.
Matrix.cpp
using namespace Math;
using namespace std;
namespace Math {
ostream& operator<<(ostream& os, const Matrix& obj) {
os << obj.XYZ << obj.ABC << '\n';
return os;
}
}
In C++14 you can use the following template to print any object which has a T::print(std::ostream&)const; member.
template<class T>
auto operator<<(std::ostream& os, T const & t) -> decltype(t.print(os), os)
{
t.print(os);
return os;
}
In C++20 Concepts can be used.
template<typename T>
concept Printable = requires(std::ostream& os, T const & t) {
{ t.print(os) };
};
template<Printable T>
std::ostream& operator<<(std::ostream& os, const T& t) {
t.print(os);
return os;
}
I would like to simplify this a little with an example that overloads << to print an array.
First pass both the object types around the << operator
create a function to overload the operator as follows.
#include<iostream>
using namespace std;
void operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
os << arr[i] << " ";
}
os << endl;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << arr;
}
if cascading of operators is also required make sure to return cout object
in the overloaded function as follows,
#include<iostream>
using namespace std;
ostream& operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
cout << arr[i] << " ";
}
cout << endl;
return os;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 11,22,33,44,55,66,77,88,99,100 };
// cascading of operators
cout << arr << arr2;
}

Do I really need to bend over backwards for a friend operator<< for a class in a namespace?

I want to implemnent an operator<< for streaming my class (say it's named Paragraph). Class Paragraph has some private data, for which reason I want the (freestanding) operator<< function to be a friend. So, I do as suggested, e.g., here on SO. friend statement, implement the operator<< and all is well.
But now I want to put Paragraph inside a namespace, say namespace foo. It no longer works! If I write:
namespace foo {
class Paragraph {
public:
explicit Paragraph(std::string const& init) :m_para(init) {}
std::string const& to_str() const { return m_para; }
private:
friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
std::string m_para;
};
} // namespace foo
The compiler tells me I've befriended foo::operator<<, not ::operator<<. Ok, fair enough. So, I replace the friend line with:
friend std::ostream & ::operator<<(std::ostream &os, const Paragraph& p);
but I get an error again (from GCC 5.4.0), telling me the ::operator<< has not having been declared. Ok, let's declare it then. Will this work?:
namespace foo {
std::ostream & ::operator<<(std::ostream &os, const foo::Paragraph& p);
class Paragraph {
public:
explicit Paragraph(std::string const& init) :m_para(init) {}
std::string const& to_str() const { return m_para; }
private:
friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
std::string m_para;
};
} // namespace foo
Nope, it doesn't know about Paragraph when reading the declaration of ::operator<. Ok, let's forward-declare:
namespace foo {
class Paragraph;
std::ostream & ::operator<<(std::ostream &os, const foo::Paragraph& p);
class Paragraph { /* actual definition here */ } }
std::ostream & operator<<(std::ostream &os, const foo::Paragraph& p) { /* impl */ }
no luck. I get the weird error:
f.cpp:23:16: note: candidate: std::ostream& operator<<(std::ostream&, const foo::Paragraph&)
std::ostream & operator<<(std::ostream &os, const foo::Paragraph& p)
^
f.cpp:11:15: note: candidate: std::ostream& operator<<(std::ostream&, const foo::Paragraph&)
std::ostream& ::operator<<(std::ostream &os, const foo::Paragraph& p);
... and here I was thinking the global namespace and the :: namespace are the same thing... arent' they? (sigh). No matter, let's move the declaration out of the namespace:
class foo::Paragraph;
std::ostream & operator<<(std::ostream &os, const foo::Paragraph& p);
namespace foo { class Paragraph { /* actual definition here */ } }
std::ostream & operator<<(std::ostream &os, const foo::Paragraph& p) { /* impl */ }
Still not good enough, now I get the "'foo' has not been declared" error. (granshes teeth) fine! Be that way!
namespace foo { class Paragraph; }
std::ostream & operator<<(std::ostream &os, const foo::Paragraph& p);
namespace foo { class Paragraph { /* actual definition here */ } }
std::ostream & operator<<(std::ostream &os, const foo::Paragraph& p) { /* impl */ }
so this, but no less than this, works. That's terrible! Surely there must be some kind of less verbose way to do it... right?
Note: Assume the operator<< can't be inlined and must be defined separately.
It seems your problem stems from not realizing how ADL can find the right operator<< as long as it is the same namespace as Paragraph. To expand on your first example
// this is what you have already
namespace foo {
class Paragraph {
public:
explicit Paragraph(std::string const& init) :m_para(init) {}
std::string const& to_str() const { return m_para; }
private:
friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
std::string m_para;
};
} // namespace foo
// Now we can add a definition here, or in a different TU
namespace foo {
std::ostream& operator<<(std::ostream& os, const Paragraph& p) {
return os << p.m_para;
}
} // namespace foo
int main() {
foo::Paragraph p("hello");
// finds your operator<< using adl
std::cout << p << '\n';
}
Just put the definition of the << operator in the namespace along with Paragraph. Argument-dependent lookup will find it when you insert a Paragraph object into a stream.
// myheader.h:
namespace ns {
struct x {
/* ... */
friend std::ostream& operator<<(std::ostream&, const x&);
};
}
// myheader.cpp:
#include "myheader.h"
namespace ns {
std::ostream& operator<<(std::ostream& os, const x& xx) {
os << xx.whatever() << '\n';
return os;
}
}
Or, if it's small enough to warrant inlining, just do that:
// myheader.h:
namespace ns {
struct x {
/* ... */
friend std::ostream& operator<<(std::ostream&, const x&);
};
inline std::ostream& operator<<(std::ostream& os, const x& xx) {
os << xx.whatever() << '\n';
return os;
}
}

How do I properly overload the operator in this specific case using C++

I am new to C++ programming and am having trouble implementing this operator overloading. It gives the error that no operator "<<" matches these operands.
class class1{
public:
bool operator==(class1 &);
friend ostream & operator<<(ostream &, class1 &);
private:
string name;
};
/*Friend ostream & operator <<*/
ostream & operator << (ostream & os, class1 & obj){
os << obj.name;
return os;
}
Someone mentioned I need another overloaded operator, but I can't figure out how to make it work with another overloaded operator
Here is the situation with your code; you have a private member string variable within your class where no outside object can set this variable. Your class does not contain a defined constructor nor a setting method. When I tried your code I had to change your operator declaration and definition from this:
std::ostream& operator<<( std::ostream& os, class1& obj );
to this:
std::ostream& operator<<( std::ostream& os, const class1& obj );
in order for it to compile. However when it came to building the project I was getting a Linker Error of an unresolved identifier. What was happening here is that the ostream object that you are declaring as a friend to your class object does know about the private member string but it can not do anything with it since this string is empty or not valid. I changed your class to this:
#include <conio.h>
#include <string>
#include <iostream>
class class1 {
friend std::ostream& operator<<( std::ostream& out, const class1& other );
private:
std::string m_strName;
public:
explicit class1( std::string& strName ) : m_strName( strName ) {}
void setName( std::string& strName ) { m_strName = strName; }
std::string getName() const { return m_strName; }
};
std::ostream& operator << ( std::ostream& out, class1& obj ) {
out << obj.m_strName << std::endl;
// out << obj.getName() << std::endl;
return out;
}
int main() {
class1 a( std::string( "class1" ) );
std::cout << a << std::endl;
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
This compiles, builds, links and executes properly and displays appropriate text and exits with a value of 0 for no errors. I am using MSV2013 on a Win7 machine. The main issue was that since your class had no way to populate its string member upon construction the ostream operator object could not resolve the variable in use.
The overload operator<<(std::ostream&, std::string) is actually defined by #include <string>.
Although std::string is also defined by that header, it is still possible for std::string to be defined but not this operator overload, if you did not include that header.
The C++ standard requires that certain headers provide certain features, but it does not prohibit that feature also being provided by another header. In your case, the compiler/library writer has decided that implementing some other feature in another header was most easily done by defining std::string, but it would have done this by having a separate file defining std::string which is included both by <string> and by the other header.
remove the keyword "friend" for ostream if you intent for it to be a public member. If your want ostream to be friend move it above public:
operator== should have two const parameter, const if you do not intend to change.
friend ostream & operator<<(ostream &, const class1 &);
public:
bool operator==(const class1& x, const class1& y);
or
public:
bool operator==(const class1& x, const class1& y);
ostream & operator<<(ostream &, const class1 &);
make operator << second parameter a const might help
ostream & operator << (ostream & os, const class1 & obj){
os << obj.name;
return os;
}

Inaccessible member function when trying to overload << stream as friend?

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?