#include <iostream>
using namespace std;
class family
{
private:
double weight;
double height;
public:
family(double x,double y);
~family();
double getWeight();
double getHeight();
double setWeight();
double setHeight();
bool operator==(const family &,const family &);
};
bool family::operator ==(const family &a,const family &b)
{
return(a.getWeight() == b.getWeight());
}
family::family(double x, double y)
{
weight = x;
height = y;
}
double family::getWeight()
{
return weight;
}
double family::getHeight()
{
return height;
}
family::~family(){}
int main()
{
family a(70.0,175.2);
family b(68.5,178.2);
if(a==b)
cout << "A is bigger than B" << endl;
else
cout << "A is smaller than B" << endl;
return 0;
}
I want to use method for overloading equal operator.
However, I have an error message
"no match for ‘operator ==’ in ‘a == b’"
Why this error message come up ?
Furthermore, I want to know why there is reference symbol "&" in (const family &,const family &).
Please, give me some advice for modifying my code b.b.
Why this error message come up ?
If you implement a binary operator as a member function, it only receives the right-hand side as an argument, the left-hand side is the calling object. If you write:
a == b
the compiler looks for a function that meets either:
(return type) (type of lhs)::operator==( (type of rhs));
or
(return type) operator==( (type of lhs), (type of rhs) );
Note: (return type) could be anything, though normally you'd want to return bool here. It doesn't affect what the compiler looks for when making the function call.
Your function signature instead is:
(return type) (type: family)::operator==( (type: family), (type: family) );
This is expecting three arguments (one implied)!
Furthermore, I want to know why there is reference symbol "&" in (const family &,const family &).
const family & is the type of argument the function accepts. It receives objects of family type by reference (that is, it uses the original objects rather than making a copy of them), and it promises not to modify them (const). The compiler will enforce this promise. Since the function doesn't need to modify either object, and there's no reason to make a full copy of either, this is exactly the right signature to use. For a non-member function.
For a member function you have to modify it slightly:
class family
{ // ...
bool operator==(
// ...
}
This is fine so far, we don't have to change anything. Your parameter list should only include the right-hand side argument, so:
bool operator==(const family&)
But we're not quite done. Remember how the non-member function uses "const family&" as the parameter type? Somehow we need to mark the calling object as const too. We do this by adding const at the very end:
bool operator==(const family&) const;
(The calling object is already available as though by reference.)
When you go to write the function itself, simply use:
bool family::operator==(const family &rhs) const {
...
}
Then for the body of the function, you can either use the members of the calling object and the rhs directly, or call their relevant functions, like so:
return weight == rhs.weight; // direct member access
or
return getWeight() == rhs.getWeight(); // using functions
If you implement operator== as a member function, it only takes one parameter.
Or in practice, you could implement it as a free function
class family
{
private:
double weight;
double height;
public:
family(double x,double y);
~family();
double getWeight() const;
double getHeight() const;
double setWeight();
double setHeight();
};
bool operator==(const family &a,const family &b)
{
return a.getWeight() == b.getWeight();
}
Update:
AS operator== takes const family objects, you need to make getWight()/getHeight() function const.
You may do the below changes in the code:
double getWeight() const;
.
.
bool operator==(const family &);
.
.
bool family::operator==(const family &b)
{
return weight == b.getWeight();
}
Two possibilities:
(1) If you want to keep your definition same:
declare as non-member and friend:
friend bool operator==(const family &,const family &);
define as:
bool operator ==(const family &a,const family &b)
{
return(a.getWeight() == b.getWeight());
}
(2) Declare as a member (implicit argument is the current object pointed by this):
declare as non-member and friend:
bool operator==(const family &);
define as:
bool family::operator ==(const family &a)
{
return(this->getWeight() == a.getWeight());
}
Related
I have a set composed of objects; in order to work the operator< must be defined for ordering the objects inside the set. If I define the operator< as a friend function, it works; if I define the operator< as a member function I get the error:
Error C2678 binary '<': no operator found which takes a left-hand >operand of type 'const _Ty' (or there is no acceptable conversion).
I do not understand why the version of operator< implemented as member function does not work/what should be changed about it.
I provide bellow a simplified example of the problem case:
class TestObj
{
private:
int m_a;
public:
TestObj(int a): m_a{a} {}
/* operator < as friend function works */
/*friend bool operator< (const TestObj& t1, const TestObj& t2)
{
return t1.m_a < t2.m_a;
}*/
/* operator < as member function does not work! */
bool operator< (const TestObj& t2)
{
return m_a < t2.m_a;
}
};
void testSetCompare()
{
std::set<TestObj> set1;
set1.insert(10);
set1.insert(20);
}
I do not understand why the version of operator< implemented as member function does not work/what should be changed about it.
You need to make the member function const. Because you declared it as 'non-const' the compiler cannot decide if yout operator willl change *this so your operator cannot be used in a when you have a const TEstObj& what is needed for insert
bool operator< (const TestObj& t2) const
{
return m_a < t2.m_a;
}
will do the job.
Edit: The "No acceptable converson" means that it cannot convert from const TestObj& to TestObj& because it would break the rules of const. (and your operator needs a TestObj&)
I'm trying to define an == operator within a struct, like this:
struct names {
string fname;
string lname;
bool operator==(names a, names b) {
return (a.fname == b.lname);
}
};
However, the compiler says:
..\src\trash.cpp:10:33: error: 'bool names::operator==(names, names)' must take exactly one argument
Why is this?
If you overload a binary operator as a member function, then it should only take one argument. The first operand is the object the operator is called on (i.e. *this); the second operand is the single function argument.
struct names {
//...
// better to pass by reference;
// make the function 'const' so it can be used on constant objects
bool operator==(names const & rhs) const {
return this->fname == rhs.lname;
}
};
Alternatively, you can overload it as a non-member function, with two arguments:
bool operator==(names const & lhs, names const & rhs) {
return lhs.fname == rhs.lname;
}
If this needed access to private members (which isn't the case in this example), then it would have to be a friend. You can define friends inside the class definition; in which case the code would look exactly the same as your example, only with friend in front of the function declaration.
(Of course, this isn't a sensible definition of equality since it's not symmetric. Many algorithms will break if you can have a == b but not b==a, as you can with this definition. lhs.fname == rhs.fname && lhs.lname == rhs.lname would make more sense.)
operator== is meant to compare two objects for equality. You have it appearing to compare the first and last names for different objects, presumably to catch duets like George Lazenby and Emma George.
I'd make it a member function of the class and use this for one of the objects:
bool operator== (const names &rhs) const {
return (this->fname == rhs.fname) && (this->lname == rhs.lname);
}
Do:
As member function:
struct names {
string fname;
string lname;
bool operator==(const names& rhs) const { /* Your code */ }
};
or as free function:
bool operator==(const names& lhs, const names& rhs) const { /* Your code */ }
While trying to teach myself STL, I wrote the following class:
class Person{
public:
...
bool operator<(const Person& p) const; // sorts by weight
friend bool compareWeight(const Person &p, const int& wt); //true if wt<p.weight
friend bool compareWeight(const int& wt, const Person &p);
...
private:
int age;
int weight;
};
Operator< is defined as:
bool Person::operator<(const Person& p) const{
if (weight<p.weight)
return true;
else
return false;
}
Why doesn't this work:
// get lower_bound for weight = 50
vector<Person>::iterator itr = lower_bound(v.begin(),v.end(),50,compareWeight);
It throws:
error C2914: 'std::lower_bound':cannot deduce template argument as function argument is ambiguous
I can solve this using a dummy person, with weight = 50, and then calling lower_bound:
vector<Person>::iterator itr = lower_bound(v.begin(),v.end(), dummy);
But its obviously not very elegant, can someone please help me getting compareWeight to work? Also, any suggestions about best approach in such a case will be great. No Boost or C++11 please, sorry.
Instead of providing the two friend functions, you can provide a single function object that will do both operations.
struct CompareWeight {
bool operator()(const Person&, int) const;
bool operator()(int, const Person&) const;
};
Then you can call the algorithm as:
std::lower_bound(std::begin(v), std::end(v), CompareWeight());
Note: I agree with jrok that only one overload should be needed, but it seems that your implementation (which need not fully comply with the standard) requires the other direction, if that is the case this provides for a simple workaround.
Compiler needs to know the exact signature of the function to deduce the last argument of lower_bound. But since compareWeight is overloaded, it can't decide which one to take. Thus, you need to manualy cast to the right function pointer:
typedef bool(*Comp)(const Person&, const int&);
lower_bound(v.begin(),v.end(),50,static_cast<Comp>(&compareWeight));
Personaly, I'd do what you did with dummy parameter.
Off topic suggestion: pass primitive types by value, it's faster.
friend bool compareWeight(const Person &p, int wt);
I implemented a custom TimeStruct class, where I declare < operator as follows
bool operator<(const TimeStruct t2) const;
implementation is as follows.
bool TimeStruct::operator<(const TimeStruct t2) const
{
//do something, I don't include the actual implementation
return true;
}
Then I have another class X where this TimeStruct class is a member, let's call this member field Y. And I am using a vector, and I want to sort this vector on Y field of Class X. Therefore I will need to specify a method which might serve as a basis for the vector's sort method.
Therefore I declared an additional method in X to compare different X's.
bool compareX(const X& x1, const X& x2) const;
and the implementation is as follows:
bool X::compareX(const X& x1, const X& x2) const
{
return (x1.Y.operator<(x2.Y));
}
Unfortunately this code does not compile. I am receiving the following error.
No matching function call for TimeStruct::operator<(const TimeStruct&) const
candidates are : bool TimeStruct::operator<(TimeStruct&) const
I've been scratching my hair for the last hour, can anybody point out what I've been doing wrong.
You need to pass by const reference in your TimeStruct operator:
bool operator<(const TimeStruct& t2) const;
and, according to the error message, you have provided
bool operator<(TimeStruct&) const
There needs to be a const reference specifier in the operator declaration.
Furthermore, you may want to turn operator< from a member function into a friend function.
It's usually best practice.
the question may look silly ,but i want to ask..
Is there any way we can declare a method in a class with same signature but different return type (like int fun(int) and float fun(int) ) and during the object creation can we dynamically decide which function to be executed! i have got the compilation error...is there any other way to achieve this logic may be using templates...
You can always take the return value as a template.
template<typename T> T fun(int);
template<> float fun<float>(int);
template<> int fun<int>(int);
Can you decide dynamically at run-time which to call? No.
#DeadMG proposed the template based solution, however you can simply "tweak" the signature (which is, arguably, what the template argument does).
The idea is simply to add a dummy argument:
struct Foo
{
float fun(float); // no name, it's a dummy
int fun(int); // no name, it's a dummy
};
Then for execution:
int main() {
Foo foo;
std::cout << foo.fun(int()) << ", " << foo.fun(float());
}
This can be used exactly as the template solution (ie invoked from a template method), but is much easier to pull:
less wordy
function template specialization should be defined outside the class (although VC++ will accept inline definition in the class)
I prefer to avoid function template specialization, in general, as with specialization on arguments, the rules for selecting the right overload/specialization are tricky.
You can (but shouldn't*) use a proxy class that overloads the conversion operators.
Long example with actual usecase *
Let me take my example from Dot & Cross Product Notation:
[...]
There is also the possibility of having operator* for both dot-product and cross-product.
Assume a basic vector-type (just for demonstration):
struct Vector {
float x,y,z;
Vector() {}
Vector (float x, float y, float z) : x(x), y(y), z(z) {}
};
We observe that the dot-product is a scalar, the cross-product is a vector. In C++, we may overload conversion operators:
struct VecMulRet {
public:
operator Vector () const {
return Vector (
lhs.y*rhs.z - lhs.z*rhs.y,
lhs.z*rhs.x - lhs.x*rhs.z,
lhs.x*rhs.y - lhs.y*rhs.x
);
}
operator float () const {
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
private:
// make construction private and only allow operator* to create an instance
Vector const lhs, rhs;
VecMulRet (Vector const &lhs, Vector const &rhs)
: lhs(lhs), rhs(rhs)
{}
friend VecMulRet operator * (Vector const &lhs, Vector const &rhs);
};
Only operator* is allowed to use struct VecMulRet, copying of VecMulRet is forbidden (paranoia first).
Operator* is now defined as follows:
VecMulRet operator * (Vector const &lhs, Vector const &rhs) {
return VecMulRet (lhs, rhs);
}
Et voila, we can write:
int main () {
Vector a,b;
float dot = a*b;
Vector cross = a*b;
}
Btw, this is blessed by the Holy Standard as established in 1999.
If you read further in that thread, you'll find a benchmark that confirms that this comes at no performance penalty.
Short example for demonstration *
If that was too much to grasp, a more constructed example:
struct my_multi_ret {
operator unsigned int() const { return 0xdeadbeef; }
operator float() const { return 42.f; }
};
my_multi_ret multi () {
return my_multi_ret();
}
#include <iostream>
#include <iomanip>
int main () {
unsigned int i = multi();
float f = multi();
std::cout << std::hex << i << ", " << f << std::endl;
}
* You can, but shouldn't, because it does not conform to the principle of least surprise as it is not common practice. Still, it is funny.