The following class is present:
class Actor {
public:
float xpos{0};
float ypos{0};
Actor(float x, float y);
~Actor();
};
In the a static function of a management class, I want to create such an actor and insert it into a set:
class ActorManager {
private:
ActorManager();
static std::set<Actor> actors;
public:
static void addActor(float x, float y);
}
Definition:
std::set<Actor> ActorManager::actors = std::set<Actor>();
void ActorManager::addActor(float x, float y) {
Actor actor(x, y);
actors.insert(actor); // <--
}
With the marked line present, actors.insert, the compilation fails. The error states:
/usr/lib/c++/v1/__functional_base:56:21: Invalid operands to binary expression ('const Actor' and 'const Actor')
What am I missing here?
You need to overload operator< in order to use your class with std::set (it needs this in order to sort the elements).
bool operator <(const Actor& p1, const Actor& p2){
bool result=false;
if (p1.x<p2.x)
{
result=true;
}
else if (p1.x==p2.x&&p1.y<p2.y){
result=true;
}
return result;
}
//this is the correct way of overloading < operator
Related
Given the class
class objects {
public:
bool compareArea (const objects& obj) const { return this->area < obj.area; }
private:
double area;
};
I want to sort a
list<shared_ptr<objects>> myObjects;
I cannot use a lambda (since my toolchain's C++11 support is incomplete). Thus, I tried the following:
using namespace placeholders;
myObjects.sort(bind(&objects::compareArea,_1,_2));
This line is called from another file (not from a class member!). The problem is, that compareArea requires two objects as input. But I give two shared pointer to objects to it. Is there an easy way of how to include the dereferencing of the pointers into the sort-call? I want the objects::compareArea(..) function to stay as it is. I do not want this kind of solution
bool compareArea (const shared_ptr<objects>& ptr1, const shared_ptr<objects>& ptr2) {
return ptr1->area > ptr2->area;
}
// in same source-file:
myObjects.sort(bind(compareArea,_1,_2));
where compareArea is no member-function of objects. Actually an operator overloading of < would be my favourite solution.
I would strongly suggest that you never store any kind of pointer in a container.
Instead, make a handle class which supports the required arithmetic and comparison operators.
It makes for code that's easier to reason about:
class objects {
public:
objects(double w, double h) : area(w * h) {}
bool operator<(const objects& r) const { return this->area < r.area; }
private:
double area;
};
struct object_handle
{
object_handle(shared_ptr<objects> const& ptr) : ptr_(ptr) {}
static object_handle create(double w, double h) { return make_shared<objects>(w,h); }
bool operator < (object_handle const& r) const {
return *ptr_ < *r.ptr_;
}
shared_ptr<objects> ptr_;
};
int main() {
std::vector<object_handle> mylist;
mylist.push_back(object_handle::create(10, 7));
mylist.push_back(object_handle::create(2, 5));
std::sort(mylist.begin(), mylist.end());
}
Lambdas are just syntactic sugar for a class with operator(), so you can very easily write one directly (especially if you don't need captures):
struct Comparator
{
bool operator() (const shared_ptr<objects> &lhs, const shared_ptr<objects> &rhs) const
{
return lhs->compareArea(*rhs);
}
};
myObjects.sort(Comparator());
I've created a Point class and overload his operator==, and a PointSet class that has an array of pointers to Point objects.
Now, when i want to compare between two object I'm running in to unexplained compilation error when I'm tring to compare A==B but not when B==A.
i.e when im fliping the order of the object the function work as ecxpected.
I didnt find any logic between this two cases.
This is Point and PointSet classes (diffrenet header files)
class Point{
public:
Point(int x, int y);
~Point();
bool operator==(const Point& point);
private:
int _x, _y;
};
class PointSet
{
public :
PointSet(const size_t startLen);
~PointSet();
int contains(const Point *point) const
private:
Point **_pointArray;
size_t _size;
};
this is the implementation of the operator==
bool Point::operator ==(const Point& point){
return (this->_x == point.get_x() && this->_y == point.get_y());
}
And this is the function where the problem occur
int PointSet::contains(const Point *point) const{
for (int i=0; i<_size;i++){
if (*point == *_pointArray[i]){ <-----HERE
return i;
}
}
return -1;
}
this ISN'T an error if(*_pointArray[i] == *point)
the compilation error is "Can't compare structures"
Your operator== should be a const function
Try to implement
bool operator==(const Point& lhs, const PointSet& rhs){ /* do actual comparison */ }
as a friend member function. Also include:
bool operator==(const PointSet& lhs, const Point& rhs){ /* do actual comparison */ }.
This is the way you guarantee it will work.
More about this can be found here.
I'm trying to implement a operator function to solve the next error :
error: assignment of member 'Animal::weight' in read-only object weight +=amount*(0.02f);
My Animal.cpp function looks like:
void Animal::feed(float amount) const
{
if (type == "sheep"){
amount=amount*(0.02f);
weight+=amount;
}else if (type == "cow"){
weight +=amount*(0.05f);
}else if (type == "pig"){
weight +=amount*(0.1f);
}
return weight;
}
Animal.h (short version):
class Animal
{
public:
Animal(std::string aType, const char *anSex, float aWeight, QDateTime birthday);
float getWeight() const {return weight;};
void setWeight(float value) {weight = value;};
float feed(float amount) const;
void feedAnimal(float amount);
private:
float weight;
};
float operator+=(const float &weight,const float &amount);
Then I implemented a += operator.
float operator+=(const float &weight,const float &amount);
Which is also included then in the .cpp file:
Animal & operator +=(Animal &animal, float amount){
float w = animal.getWeight();
animal.setWeight(w+amount);
}
I worked with a reference so that the weight is update for every animal. So I can call the function feed, and when I want to know the result I do it with the get function:
float getWeight() const {return weight;};
But for some reason I catch the next error :
'float operator+=(const float&, const float&)' must have an argument of class or enumerated type
float operator+=(const float &weight,const float &amount);
Any solutions for this?
For use the feed function I also have a problem. I have my Farm.cpp class where i loop for all the animals in the farm.
void Farm::feedAllAnimals(float amount)
{
for (auto an : animals) {
if(an != nullptr) {
an->feed(amount);
}
}
std::cout << "all animals fed with " << amount << "kg of fodder";
}
And in my .h file I have those functions :
Public:
void feedAllAnimals(float amount);
Private:
std::vector<std::shared_ptr<const Animal>> animals;
My error:
error: passing 'const Animal' as 'this' argument of 'float Animal::feed(float)' discards qualifiers [-fpermissive] an->feed(amount);
^
You declared function feed as a const member function
void feed(float amount) const;
^^^^^
You may not change the object if it is a constant object.
As for operator
float operator+=(const float &weight,const float &amount);
then you may not overload operators for fundamental types.
I think you mean either the following
Animal & operator +=( Animal &animal, float amount);
For example
Animal & operator +=( Animal &animal, float amount)
{
animal.setWeight( animal.getWeight() + amount );
return animal;
}
or an operator declared as a member function within the class like
Animal & operator +=( float amount );
As for the vector then the template parameter must be without qualifier const if you are going to change objects pointed to by the elements of the evctor
std::vector<std::shared_ptr<Animal>> animals;
#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;
};
bool family::operator ==(const family &b)const
{
return weight==b.weight;
}
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;
}
Above the code, I can implement operator overloading with member function. However, I failed to implement operator overloading with non member function. How should i modify this code b.b
Please help me..
Basically, the only difference between a member function and a non-member function is that it's passed an implicit this pointer as well as any other arguments and it has access to private/protected members. So to transform any member function to a non-member function is to simply factor it out of the class definition. make it a friend of that class and add a parameter that's a reference to that class. Pass in an object of that class when you call it. You can also do a const& of the function.
You can use Friend Function and use objects as parameter of that function like we use in << operator.
we also can use operator without friend function :
bool operator==(const family first, const family second)
{
if(first.getWeight( ) == second.getWeight( )){
return True;
else
return False;
}
class family
{
private:
double weight;
double height;
public:
family( double x, double y );
~family( );
// getters should be const
double getWeight( ) const;
double getHeight( ) const;
double setWeight( );
double setHeight( );
};
// no reason to make it friend of class
// b/c it does not work with private/protected members
bool operator==( const family & first, const family & second );
// better to move into cpp file
bool operator==( const family & first, const family & second )
{
return first.getWeight( ) == second.getWeight( );
}
I want to construct two priority queue that has different compare method(there are two reverse priority methods named cmp1 and cmp2)
My program can't go through the compiler check.Why does such error happen and is there any better solution?
#include <iostream>
#include <queue>
#include <string>
using namespace std;
struct item
{
string name;
string sex;
string id;
double score;
friend istream& operator >> (istream &is,item& data)
{
is>>data.name>>data.sex>>data.id>>data.score;
}
/*friend bool operator < (item& a,item& b)
{
return a.score<b.score;
}*/
};
struct cmp1{
operator bool()(item& x,item& y)
{
return x.score>y.score;
}
};
struct cmp2
{
operator bool()(item& x,item& y)
{
return x.score<y.score;
}
};
int main()
{
priority_queue<item,vector<item>,cmp1> boys;
priority_queue<item,vector<item>,cmp2>girls;
item temp;
int num;
cin>>num>>temp;
for(int i=0;i<num;i++)
{
if(temp.sex=="M")
boys.push(temp);
else
girls.push(temp);
}
return 0;
}
I'm going to take a wild guess at the problem.... your comparison functors are incorrect. Instead of overloading operator bool, you need to overload the function call operator, i.e.
struct cmp1{
bool operator()(const item& x, const item& y)
{
return x.score>y.score;
}
};
struct cmp2
{
bool operator()(const item& x, const item& y)
{
return x.score<y.score;
}
};
(Perhaps this was what you intended, but just got the syntax a little wrong?)
Actually, I think the best way to do it is to use std::less and std::greater. If you have overloaded operator< and operator> for your class, you can do it like this:
std::priority_queue<item, std::vector<item>, std::greater<item>> boys;
std::priority_queue<item, std::vector<item>, std::less<item>> girls;
That way you don't have to write the functor. Don't forget to #include <functional>.
Also, don't forget that the operators have to be overloaded taking const ref arguments (you can also take them by value, but that's not usually a good idea), and as const methods, like in:
bool operator<(const item& i) const {
return value < i.value;
}
bool operator>(const item& i) const {
return value > i.value;
}
Change your operator functions to this:
struct cmp1{
bool operator()(item& x,item& y)
{
return x.score>y.score;
}
};
struct cmp2
{
bool operator()(item& x,item& y)
{
return x.score<y.score;
}
};
You have defined the methods in the comparison classes wrong.
Try the following code:
struct cmp1{
bool operator()(item& x,item& y)
{
return x.score>y.score;
}
};
You have defined the methods as operator bool() ....
Also it is nice to add const to the parameters, as const item& x for showing that you won't change their values, as well a const at the end of the function definition:
bool operator()(const item& x, const item& y) const {...}
for showing that you won't change the member fields too.
I will write the third correct version of the predcate
struct cmp1
{
bool operator()( const item &x, const item &y ) const
{
return x.score > y.score;
}
};
struct cmp2
{
bool operator()( const item &x, const item &y ) const
{
return x.score < y.score;
}
};