Reputation: 5745
I have a Student class. I want to overload +
operator so I can add a double variable to class. Here is Student
class:
class Student {
private:
std::string firstName;
double grade;
public:
Student(const std::string &firstName, double grade);
double getGrade() const;
friend Student operator+(double grade, const Student &student);
Student operator+(double grade) const;
};
And implementation:
Student::Student(const std::string &firstName, double grade) {
this->firstName = firstName;
this->grade = grade;
}
double Student::getGrade() const {
return grade;
}
Student operator+(double grade, const Student &student) {
return Student(student.firstName, student.grade + grade);
}
Student Student::operator+(double grade) const {
return operator+(grade, *this);
}
double + Student
is done via friend function and Student + double
goes through member function. When I compile I get this:
error: no matching function for call to ‘Student::operator+(double&, const Student&) const’
return operator+(grade, *this);
^
note: candidate is:
note: Student Student::operator+(double) const
Student Student::operator+(double grade) const {
^
note: candidate expects 1 argument, 2 provided
Why I can't call a friend function from a member function?
[UPDATE]
However when I overload <<
operator, I can call it from member function without pre-pending ::
.
friend std::ostream &operator<<(std::ostream &os, const Student &student);
and the implementation:
std::ostream &operator<<(std::ostream &os, const Student &student) {
os << student.grade;
return os;
}
Upvotes: 2
Views: 1127
Reputation: 43662
You're trying to call the member function, not the friend function (cfr. C++11 7.3.1.2/3). You should rather write
Student Student::operator+(double grade) const {
return ::operator+(grade, *this);
}
Using the ::
makes sure overload resolution occurs from the global namespace you're currently in.
Another way (less readable in my opinion) is to add the friend function to the overload resolution set
Student Student::operator+(double grade) const {
using ::operator+;
return operator+(grade, *this);
}
or, more readable, as Jarod suggested,
Student Student::operator+(double grade) const {
return grade + *this;
}
Edit: as for the "why": [class.friend]/p7 and [basic.lookup.argdep]/p3 explain that a member function with the same name "hides" during overload resolution the name of the friend function.
Upvotes: 3