I wrote this simple program to practice overloading.
This is my code:
#include <iostream>
#include <string>
using namespace std;
class sex_t
{
private:
char __sex__;
public:
sex_t(char sex_v = 'M'):__sex__(sex_v)
{
if (sex_v != 'M' && sex_v != 'F')
{
cerr << "Sex type error!" << sex_v << endl;
__sex__ = 'M';
}
}
const ostream& operator << (const ostream& stream)
{
if (__sex__ == 'M')
cout << "Male";
else
cout << "Female";
return stream;
}
};
int main(int argc, char *argv[])
{
sex_t me('M');
cout << me << endl;
return 0;
}
When I compile it, it print lots of error messages:
The error message was in a mess.
It's too hard for me to found a useful message.
sex.cpp: 在函数‘int main(int, char**)’中:
sex.cpp:32:10: 错误: ‘operator<<’在‘std::cout << me’中没有匹配
sex.cpp:32:10: 附注: 备选是:
/usr/include/c++/4.6/ostream:110:7: 附注: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostre
The argument and return from operator<< are non-const. Also it needs to be a non-member- you have written an overload for me << cout, not cout << me. Also, identifiers leading with two underscores are reserved for the implementation and using them is Undefined Behaviour.
"C++ Primer 4th Edition" Chapter 14 section 14.2 Input and Output Operators:
IO Operators Must Be Nonmember Functions, We cannot make the operator a member of our own class. If we did, then the left-hand operand would have to be an object of our class type:
// if operator<< is a member of Sales_item
Sales_item item;
item << cout;
The general skeleton of an overloaded output operator is
// general skeleton of the overloaded output operator
ostream&
operator <<(ostream& os, const ClassType &object)
{
// any special logic to prepare object
// actual output of members
os << // ...
// return ostream object
return os;
}
The first parameter is a reference to an ostream object on which the output will be generated. The ostream is nonconst because writing to the stream changes its state. The parameter is a reference because we cannot copy an ostream object.
The second parameter ordinarily should be a const reference to the class type we want to print. The parameter is a reference to avoid copying the argument. It can be const because (ordinarily) printing an object should not change it. By making the parameter a const reference, we can use a single definition to print const and nonconst objects.
The return type is an ostream reference. Its value is usually the ostream object against which the output operator is applied.
EDIT:
I tried to modify your code, and if you use __sex__ as sex_t's private member, you should write another get function to get the 'M' or 'F', and if you call it in your operator<< function, you will probably get an error, because a const reference could only call a const function, so you should make your get function a const function, just for reminde:)
When overloading for streams, you declare a << operator globally and/or as a friend (with benefits) to your class so it can access its 'private members' (ooh...). You can declare a friend inside the class to declare it globally. Do not use const on the streams.
Next, use the passed stream in your overload. In your method, you use cout when you would have used it anyway by just using the stream argument.
I have not tested this, but see if it works for you.
class sex_t
{
private:
char __sex__;
public:
sex_t(char sex_v = 'M'):__sex__(sex_v)
{
if (sex_v != 'M' && sex_v != 'F')
{
cerr << "Sex type error!" << sex_v << endl;
__sex__ = 'M';
}
}
friend ostream& operator << (ostream& stream, sex_t& sex);
};
ostream& operator << (ostream& stream, sex_t& sex)
{
if (__sex__ == 'M')
stream << "Male";
else
stream << "Female";
return stream;
}
Related
I'm switching from C to C++ and i have some basic but annoying problem with Class hermetization. I did some research here, but I'm probably really dumb and I can't use yor methods properly, could you help me?
The problem is printing private member of a class via overloaded '<<' operator.
Let's get to the code:
In file Vector.hh
#include <iostream>
class Vector {
double Val1, Val2, Val3;
public:
void PrintVector(Vector);
//There is also a constructor but it doesn't really matter
}
In File Vector.cpp
#include "Vector.hh"
#include <iostream>
void Vector::PrintVector(Vector Wek)
{
std::cout << Wek.Val1 << Wek.Val2 << Wek.Val3 << std::endl;
}
std::istream& operator >> (std::istream &Strm, Vector &Wek)
{
//It actually works with no problem so i'll pass it
}
std::ostream& operator << (std::ostream &Strm, Vector Wek)
{
Vector::PrintVector(Wek);
return Strm;
}
and in main.cpp
#include Vector.hh
#include <iostream>
using namespace std;
int main()
{
Vector Vector1;
cout << endl << " Start " << endl << endl;
cin >> Vector1;
cout << Vector1;
}
When I try to compile g++ says:
g++ -c -g -Iinc -Wall -pedantic -o obj/Vector.o src/Vector.cpp
src/Vector.cpp:12:37: error: no 'void Vector::PrintVector(Vector)' member function declared in class 'Vector'
void Vector::PrintVector(Vector Wek)
^
src/Vector.cpp: In function 'std::ostream& operator<<(std::ostream&, Vector)':
src/Vector.cpp:29:1: error: 'PrintVector' is not a member of 'Vector'
Vector::PrintVector(Wek);
make: Fatal error: Command failed for target `obj/Vector.o'
Could you please give me a hand with it so I learn basics properly?
Either a class function is static and not called on any particular class object, or it is non-static and must be called on an instance of the class, which can be used inside the function. You have mixed the approach. You need to select one of the two:
class Vector
{
static void PrintVector(const Vector& Wek)
{
std::cout << Wek.Val1 << Wek.Val2 << Wek.Val3 << std::endl;
}
};
// to call
Vector::PrintVector(Wek);
or
class Vector
{
void PrintVector() const
{
std::cout << Wek.Val1 << Wek.Val2 << Wek.Val3 << std::endl;
}
};
// to call
Wek.PrintVector();
Either is fine, but I would prefer the latter.
The other problem is how you have implemented the stream operator. This operator takes a stream to output the object to. You have called this stream Strm, but it is never used in your operator. Your print function is hardcoded to the cout stream.
I suggest you remove the PrintVector function and implement your operator as follows:
class Vector
{
friend std::ostream& operator << (std::ostream &Strm, const Vector& Wek);
};
std::ostream& operator << (std::ostream &Strm, const Vector& Wek)
{
Strm << Wek.Val1 << Wek.Val2 << Wek.Val3 << "\n";
return Strm;
}
Now you can output to any type of stream, such as a file stream. You also needed to declare the operator as a friend to allow it to access the private members.
I changed some parameters to reference to increase speed and also replaced endl with "\n" which is faster when writing to files (you can google why).
You may want to consider adding spaces between the output members, as this makes it easer to read back.
Hope this helps.
Your error is simple. You cannot use an instance method without an object. Try:
Wek.PrintVector();
Also, pass it by constant reference, don't copy.
General way to do this is to make operator<<() a friend function of the class. Friend function can access private members of the class. So operator<<() can directly access private members for printing them. Refer sample.
Defining a public function PrintVector for printing is a bad idea. Since it is public, user (developer using your class) might start using it instead of << operator. You don't want user to use it.
I was practicing some c++ (trying to leave Java), and I stumbled on this annoying error saying:Error: No operater << matches these operands. I've searched this website for a clear answer and no luck, I did find that I'm not the only one.
This error is in my .cpp file, there are other errors, but I'm not paying any mind to them right now.
void NamedStorm::displayOutput(NamedStorm storm[]){
for(int i = 0; i < sizeof(storm); i++){
cout << storm[i] << "\n";
}
}
Something is up with the "<<" im not sure whats going on.
Since you are trying cout a class object you need to overload <<
std::ostream& operator<<(ostream& out, const NamedStorm& namedStorm)
You must overload the << operator in order to redirect your object into a stream.
You can overload as a member function, but in this case you must use the syntax object << stream in order to use that overloaded function.
If you wish to use this syntax stream << object then you must overload the << operator as a 'free' function, that is, not a member of your NamedStorm class.
Here is a working example:
#include <string>
#include <iostream>
class NamedStorm
{
public:
NamedStorm(std::string name)
{
this->name = name;
}
std::ostream& operator<< (std::ostream& out) const
{
// note the stream << object syntax here
return out << name;
}
private:
std::string name;
};
std::ostream& operator<< (std::ostream& out, const NamedStorm& ns)
{
// note the (backwards feeling) object << stream syntax here
return ns << out;
}
int main(void)
{
NamedStorm ns("storm Alpha");
// redirect the object to the stream using expected/natural syntax
std::cout << ns << std::endl;
// you can also redirect using the << method of NamedStorm directly
ns << std::cout << std::endl;
return 0;
}
The function which is called from the free redirection overload must be a public method of NamedStorm (in this case we are calling the operator<< method of the NamedStorm class), OR the redirection overload must be a friend of the NamedStorm class in order to access private fields.
I need to overload the << operator for streams to work with built-in types. For strings it's not a problem, since I simply overload the function like this:
ostream& operator<<(ostream& os, const char* str) { /*...*/ }
This works because this function is global, not a member. The problem is that I need to overload the << operator for other primitive types (ints, floats, etc) but those are member functions. Is there a way I can do this? I need it to work with not only cout but other streams as well. Thanks in advance.
You shouldn't try to change what the operator in std::cout << 3; does. It's part of a standard API. If you need to output in some format which stream manipulators can't support, then for example you could write a little wrapper:
struct MyFormatter {
MyFormatter (ostream &o) : o(o) {}
ostream &o;
};
MyFormatter &operator<<(MyFormatter &mf, int i) {
mf.o << "int(" << i << ")"; // or whatever
return mf;
}
Then use it like this:
MyFormatter mf(std::cout);
mf << 1 << "," << 2 << "," << 3;
In C++, operator overloads require at least one operand of a "class type" or enumeration type.
The point is you are not allowed to overload operator for primitive types.
http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.10
class object_1
{
public:
...
friend ofstream& operator<<(ofstream &out, const object_1 &obj_1);
friend object_2;
private:
char *pCh_mem1;
char *pCh_mem2;
int *pInt_mem1;
int *pInt_mem2;
};
class object_2
{
public:
...
friend ofstream& operator<<(ofstream &out, const object_2 &obj_2);
friend object_1;
};
Object1's implementation file is typical. Ctor, Dtor and some methods. I havent posted the method declarations in the header because their irrelevant to my problem.
It is very important that I discuss the objects lifetime.It is something that I really need to understand. Whats happening is that the operator overload function is then invoked when I call object_2 in main. So then the operator overload function is called:
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
here we are:
void object_1::display(std::ostream &out)
{
out << left << setw(28) << "Person" << setw(20) << "Place" ;
out << right << setw(5) << "Thing" << setw(5) << "Idea" << endl;
out << left << setw(28) << "----" << setw(20) << "--------" ;
out << right << setw(5) << "----- " << setw(5) << "------" << endl;
}
At the top of the implementation file is the IOMANIP library. So setw(X) and everything are defined. Im getting 0's all prinited to the console. Did my object go out of scope? I think so because when i do all these before I need to, it works fine. That is, when I call this function n e where else than in the body of the operator overload it works. I think because the object is redeclared:
ostream& operator<<(ostream& out, const object_2& obj_2);
then after I print the formatting method I need to print the information that was passed in from main to the first object's ctor; object_1. When that happens we are in the overload function which is similar and its the same implementation file. Im calling both methods from the overload in the second objects overload function:
ostream& operator<<(ostream& out, const object_1& obj_1)
{
out << obj_1.pCh_mem1 << obj_1.pCh_mem2;
return out;
}
// main
object_2 obj_2(4);
static void method1()
{
//do stuff
}
static void method2()
{
//do stuff
}
static void method3()
{
//do stuff
}
int main(void)
{
method1();
method2();
method3();
cout << obj_2;
return 0; // and such
}
Once objc_2 is called like u see above, the operator overload for object2's class will then be called. I cant use any of my private members because its an illegal operatation. I guess my questions is. How can i print my private members from object1 in my object2's operator overloading function? static_cast's? I have a random snippet from main, Its complicated and I cant alter it.
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
What i've been trying to do, like you see above is call the other objects methods, and get the info from their. But that info is all NULL!! Im hopping from one I.F. to the next and its all NULL!!
AFAICT, object_1 and object_2 are unrelated classes (except that they are friends). So an object_2 does not have any state relevant to an object_1.
Therefore, when you try to print an object_2 as if it were an object_1, this cannot possibly work. It is surprising that this call works at all:
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
since there is no object_1 around here for which a method can be called (but then, you probably didn't mean this to be real code, since it's missing a semicolon also).
It's not completely clear what you want to achieve. Maybe you want object_2 to inherit from object_1, so that any object_2 will also have the members pCh_mem1 etc? Maybe you want a member of object_2 to be an object of type object_1?
ostream& operator<<(ostream& out, const object_2& obj_2)
{
out << object_1[thatIndexThatIstoreditAt]
return out;
}
I need to write a few reports on this stuff. =)
I am trying to write a simple audit class that takes input via operator << and writes the audit after receiving a custom manipulator like this:
class CAudit
{
public:
//needs to be templated
CAudit& operator << ( LPCSTR data ) {
audittext << data;
return *this;
}
//attempted manipulator
static CAudit& write(CAudit& audit) {
//write contents of audittext to audit and clear it
return audit;
}
private:
std::stringstream audittext;
};
//to be used like
CAudit audit;
audit << "Data " << data << " received at " << time << CAudit::write;
I recognise that the overloaded operator in my code does not return a stream object but was wondering if it was still possible to use a manipulator like syntax. Currently the compiler is seeing the '<<' as the binary right shift operator.
Thanks for any input,
Patrick
To make it work you have to add overload of operator << for functions,
than call the function from it:
class CAudit
{
//...other details here as in original question
CAudit& operator << (CAudit & (*func)(CAudit &))
{
return func(*this);
}
};
CAudit audit;
audit << "some text" << CAudit::write;
Binary shift operator and stream operator is the same operator. It is completely legal to overload operator+ for your class to write "Hello world" on std::cout (although it is a very bad idea). The same way C++ standard authors decided to overload operator<< for streams as writing to the stream.
You didn't write clearly what is your problem. My guess is compilation error. The best thing in this case is to quote the error message. If I am right, the problem is, that you defined only operator<< for LPCSTR, and then you want it to work function object on the right side.
You use word "manipulator", but you misunderstand something. Manipulator for a stream (stream from STL) is a function that performs some actions on the stream it is written to. And it works only because of this overload:
ostream& operator<< (ostream& ( *pf )(ostream&));
which takes a function and applies it to a stream.
Similarly you need:
CAudit& operator<< (CAudit& ( *pf )(CAudit& audit))
{
return (*pf)(audit);
}
Wouldn't this
class CAudit
{
public:
template< typename T >
CAudit& operator<<( const T& data )
{
audittext << data;
return *this;
}
class write {};
void operator<<( const write& data )
{
/* whatever */
}
private:
std::stringstream audittext;
};
do what you want?
I do something very similar for tracing, but use a stringstream. This ensures that all 3rd party operator << () and manipulators work. I also use the desctructor instead of the customer write manipulator.
class DebugStream
{
public:
DebugStream(short level, const char * file, int line) {
sstream << "L" << level << "\t" << file << "\t" << line << "\t";
}
~DebugStream() { write(sstream.str()); }
std::ostream & stream() { return sstream; }
private:
std::stringstream sstream;
DebugStream(const DebugStream &);
DebugStream & operator=(const DebugStream &);
};
This is then made available with some macros:
#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()
And the code just uses the macros
DBG_INFO << "print some debug information";
You don't need a specific write manipulator to flush the data to the log file. When the anonymous DebugStream object goes out of scope (once control leaves the line) the the contents are automatically written.
Although I usually avoid macros in this case the use of the if statement means you don't have the overhead of building the trace line unless you actually require it.
Returning the ostream via the stream() method enables this to work for global member functions, as anonymous objects cannot be passed as non-const reference parameters.