I've got these instructions for an assignment that have put me through a loop here. I need to overload the insertion operator to print out an objects datamembers. However, it states that the overloader has to be a non-friend helper operator.
If that's the case, how can it ever access the private datamembers if its not a 'friend'? And if this is possible, why should I avoid using 'friend'?
Here is what it says word for word:
a helper non-friend operator that inserts the stored string into the left ostream operand.
This operator prefaces the string with the number of the insertion and increment that number
I'm somewhat new to C++ so I really appreciate the help.
If it's not a friend, it needs to use the object's public interface (ergo, you need to write the object's public interface to include the access required by the insertion operator).
For example, you might do something like this:
class thing {
std::string name;
public:
std::string get_name() const { return name; }
// ...
};
std::ostream &operator<<(std::ostream &os, thing const &t) {
return os << t.get_name();
}
Note that I'm definitely not recommending this as good practice--rather the contrary, I think it's often a better idea for the insertion operator to be a friend. But if you're in a class and you're prohibited from doing things the right way, you do what you have to...
Related
I have a class that represents a special number.
class SecretInteger
{
private:
unsigned int *data;
size_t length;
public:
SecretInteger operator+(const SecretInteger other) const;
}
I can't allow any other part of my code have access to the data variable. However, my operator+ function MUST be able to see it. Usually in this case I know that using the friend keyword is the only way to do it. However when I write:
friend SecretInteger operator+(const SecretInteger other);
It claims that the operator+ cannot be declared as friend, even though I've previously wrote friend std::ostream& operator<<(std::ostream& stream, const SecretInteger val); and it works fine.
What options do I have available to me? If I have a public method like
const *unsigned int getData() const; I think even then it doesn't actually make the variable returned const right? I'd really prefer not to have a getData() method and instead just declare the functions that have access as friend.
You don't declare a member function as a friend, friend is to give non-member functions access to internals, and a one operand overload of operator+ is a member function.
In any event, if you implement the binary operators properly, you shouldn't need to give out friendship at all. Implement += as a member function (no need for friend, a class is always "friends" with itself), then implement a non-member + operator in terms of +=, which uses +='s access to the internals to avoid the whole issue of friendship.
The basic rules for overloading can be found here and should help a lot.
I have a value-semantic class that I'd like to be "showable" in the same sense as Haskells Show class, or Python provides a universal __str__() function.
In c++:
I could overload operator<<(ostream&, ...) so I can output my class to e.g. cout
I could overload operator std::string() so my class converts to std::string
I could overload operator const char*() so my class converts to const char *.
I could write a str() member, or a to_string(...) free function
Each of these functions could be defined in terms of the other. Is one option better over the others? Are these all the options? What would the most elegant way be to do this given c++11/14/17?
The question is going to be put in hold in a very few minutes, but I will still share my thoughts here.
First, of all, we can remove const char* / std::string() operator overloads from the list. If the class is not a string, it should not be convertible to string, and serialization enablement does not make your class a string.
As for str(), to_string and operator << they a pretty equivalent. However, since for any complex class to_string() and str() are very likely to use ostreams internally, I believe, operator << is the best option.
I don't know whether it's best practice or not but...
for debugging I always define operator<< which gives a summarised output in text form (this means it's easy to stream objects to log files)
for formatted output I would probably choose to implement this in terms of free functions: detail::x_detail_writer write_details(const X&) and then give detail::x_detail_writer (which is a functor) an operator<< overload
for anything but the most trivial object I implement to_string in terms of operator<< if at all.
for aiding with debugging output we have a helper class which goes something like this:
template<class T>
struct make_writeable {
friend std::ostream& operator<<(std::ostream& os, const T& t) {
// example prefix...
os << demangle(typeid(T).name()) << "{";
t.write(os);
// example postfix:
os << " }";
return os;
}
};
then derive some class from this and give it a member function called write:
struct X : make_writeable<X>
{
void write(std::ostream& os) const {
// write out members here. they will appear within the prefix and postfix
}
};
I'm a bit confused about what exactly this line of code means in my header file.
friend ostream & operator << (ostream &, const something &);
Can someone clarify for me?
That line of code says that the operator << is a friend of something (since it's listed in the something class definition). This means that that operator << function can access the variables inside there.
The & here as the parameters mean that you pass in objects when calling the method and those parameters will just be another name for those parameter objects. Returning ostream & means that you're going to return the ostream parameter so that you can connect << expressions together avoiding creating a new "cout" when using the one global cout is what is needed.
As mentioned in many places, friend is a bypass to the normal protection mechanisms of C++ - it allows the function in question to access protected/private members, which normally only class members can do.
You'll often seen operators declared friends, because operators are never inside the class itself, but often need to modify something in the class and/or access private information. I.E. you may not want an external function to be able to muck with your internal pointers etc, but you may want to be able to print them out for status etc. You don't see them used very often otherwise - technically, it breaks encapsulation - but operators are kind of a special case.
A C++ class may declare another class or a function to be a friend. Friendly classes and methods may access private members of the class. So, the free operator method <<, not defined in any class, may insert somethings into a stream and look at and use the private members of something to do its work. Suppose something were complex:
class complex {
private:
double re;
double im;
public:
complex(double real = 0.0, double imag = 0.0) : re(real), im(imag) {}
friend ostream & operator<<(ostream& os, complex& c);
};
ostream & operator<<(ostream& os, complex& c){
os << c.re << std::showpos << c.im;
return os;
}
The friend keyword can name either functions or entire classes. In either case, it means that the implementation of the named function, or the named class, is allowed to access private and protected members of the class in which the friend declaration appears.
In this case, it means that this particular overload of the operator<< function is allowed to access internals of the something class, in order to write then to an output stream such as std::cout.
Following is the abstraction of string class.
class string {
public:
string(int n = 0) : buf(new char[n + 1]) { buf[0] = '\0'; }
string(const char *);
string(const string &);
~string() { delete [] buf; }
char *getBuf() const;
void setBuf(const char *);
string & operator=(const string &);
string operator+(const string &);
string operator+(const char *);
private:
char *buf;
};
string operator+(const char *, const string &);
std::ostream& operator<<(std::ostream&, const string&);
I want to know why these two operator overloaded functions
string operator+(const char *, const string &);
std::ostream& operator<<(std::ostream&, const string&);
are not class member function or friend functions? I know the two parameter operator overloaded functions are generally friend functions (I am not sure, I would appreciate if you could enlighten on this too) however my prof did not declare them as friend too. Following are the definitions of these function.
string operator+(const char* s, const string& rhs) {
string temp(s);
temp = temp + rhs;
return temp;
}
std::ostream& operator<<(std::ostream& out, const string& s) {
return out << s.getBuf();
}
Could anyone explain this with a small example, or direct me to similar question. Thanks in Advance.
Regards
The friend keyword grants access to the protected and private members of a class. It is not used in your example because those functions don't need to use the internals of string; the public interface is sufficient.
friend functions are never members of a class, even when defined inside class {} scope. This is a rather confusing. Sometimes friend is used as a trick to define a non-member function inside the class {} braces. But in your example, there is nothing special going on, just two functions. And the functions happen to be operator overloads.
It is poor style to define some operator+ overloads as members, and one as a non-member. The interface would be improved by making all of them non-members. Different type conversion rules are applied to a left-hand-side argument that becomes this inside the overload function, which can cause confusing bugs. So commutative operators usually should be non-members (friend or not).
Let's talk about operator +. Having it as a non member allows code such as the following
string s1 = "Hi";
string s2 = "There";
string s3;
s3 = s1 + s2;
s3 = s1 + "Hi";
s3 = "Hi" + s1;
The last assignment statement is not possible if operator+ is a member rather than a namespace scope function. But if it is a namespace scope function, the string literal "Hi" is converted into a temporary string object using the converting constructor "string(const char *);" and passed to operator+.
In your case, it was possible to manage without making this function a friend as you have accessors for the private member 'buf'. But usually, if such accessors are not provided for whatever reason, these namespace scope functions need to be declared as friends.
Let's now talk about operator <<.
This is the insertion operator defined for ostream objects. If they have to print objects of a user defined type, then the ostream class definition needs to be modified, which is not recommended.
Therefore, the operator is overloaded in the namespace scope.
In both the cases, there is a well known principle of Argument Dependent Lookup that is the core reason behind the lookup of these namespace scope functions, also called Koenig Lookup.
Another interesting read is the Namespace Interface Principle
Operators can be overloaded by member functions and by standalone (ordinary) functions. Whether the standalone overloading function is a friend or not is completely irrelevant. Friendship property has absolutely no relation to operator overloading.
When you use a standalone function, you might need direct access to "hidden" (private or protected) innards of the class, which is when you declare the function as friend. If you don't need this kind of privileged access (i.e. you can implement the required functionality in terms of public interface of the class), there's no need to declare the function as friend.
That's all there is to it.
Declaring a standalone overloading function as friend became so popular that people often call it "overloading by a friend function". This is really a misleading misnomer, since, as I said above, friendship per se has nothing to do with it.
Also, people sometimes declare overloading function as friend even if they don't need privileged access to the class. They do it because a friend function declaration can incorporate immediate inline definition of the function right inside the class definition. Without friend one'd be forced to do a separate declaration and a separate definition. A compact inline definition might just look "cleaner" in some cases.
I'm a bit rusty with C++ overloads but I would complete the above answers by this simple memo :
If the type of the left-hand operand is a user-defined type (a class, for instance), you should (but you don't have to) implement the operator overloading as a member function. And keep in mind that if these overloads -- which will most likely be like +, +=, ++... -- modify the left-hand operand, they return a reference on the calling type (actually on the modified object). That is why, e.g. in Coplien's canonical form, the operator= overloading is a member function and returns a "UserClassType &" (because actually the function returns *this).
If the type of the left-hand operand is a system type (int, ostream, etc...), you should implement the operator overloading as a standalone function.
By the way, I've always been told that friend keyword is bad, ugly and eats children. I guess it's mainly a matter of coding style, but I would therefore advice you to be careful when you use it, and avoid it when you can.
(I've never been faced to a situation where its use was mandatory yet, so I can't really tell ! )
(And sorry for my bad English I'm a bit rusty with it too)
Scy
I have a vector of Student objects which I want to sort using #include <algorithm> and sort(list.begin(), list.end());
In order to do this, I understand that I need to overload the "<" operator but after trying (and failing) with several methods suggested online, I am running out of ideas.
Here is my latest attempt:
In Student.h...
...
using namespace std;
class Student
{
friend bool operator <(const Student& first, const Student& second);
public:
...
private:
...
};
And in Student.cpp...
...
#include "Student.h"
using namespace std;
...
bool operator <(const Student& first, const Student& second)
{
return first.Name() < second.Name();
}
where "Name()" is a constant function which returns a string.
The program compiles and runs, but my operator function is never called during the sort and when I tried comparing two Student objects like s1 < s2 I got an "error: overloaded operator not found"
How can I correctly overload this operator so that my sort will work as I intend?
You didn't say which compiler you were using, but I suspect you're using a fairly recent one that implements the "friend is not a declaration" rule. The friend statement inside the class doesn't serve as a function declaration; other modules that include Student.h don't see any declaration of the function. It's visible only inside the Student.cpp file. (Older compilers don't have this rule, and treat a friend declaration as a function declaration.)
The function doesn't need to be a friend, since it doesn't use any private members of the Student class (I'm assuming Name() is public). Move the function declaration outside the class, and replace "friend" with "extern", and it should work.
It is possible to make the operator a member function, as some posters above suggested, but it isn't necessary. Making comparison operators member functions is generally frowned upon, because it means that the two arguments aren't treated symmetrically (one is the invisible "this" argument, the other is a normal function argument), which can lead to surprising results in some cases (for example, different type conversions may be applied to the arguments).
I wouldn't use a friend here, and I'm not sure it works at all. What I would use is...
class Student
{
public:
bool operator< (const Student& second) const;
};
bool Student::operator< (const Student& second) const
{
return (Name() < second.Name());
}
Note the trailing const, indicating that within operator<, *this is constant.
EDIT I cannot delete this answer because it was accepted, but I would if I could. I also can't replace it with a correct one. See Drew Dormanns comment below, and Ross Smiths answer.
By the way, with a function this simple I would personally just do this, unless the style guide bans the definition of functions inside class definitions:
class Student
{
friend bool operator <(const Student& first, const Student& second)
{
return first.Name() < second.Name();
}
...
};
This form of the "friend" declaration lets you define a non-member operator< inside the body of the class. It's still a friend, so Name() can be private if desired.
Well, you could do it as an internal operator:
class Student
{
public:
bool operator <(const Student& second) const;
...
private:
...
};
With an implementation comparing 'this' to second. The question in my mind is: Does the 'Name' method come in a const flavor? Because if it doesn't, then you can't write a const method that uses it.