So i have this:
class Grup : public Shape
{
private:
std::vector<Shape *> continut;
public:
static const std::string identifier;
Grup(){};
~Grup(){
continut.clear();
};
void add(Shape *);
void remove(Shape *);
void output(std::ostream &) const;
void readFrom(std::istream &);
void moveBy(int, int);
friend std::ostream &operator<<(std::ostream &, const Grup &);
}
and i want to implement the remove function.
i tried this:
void Grup::remove(Shape *s)
{
vector<Shape*>::iterator it;
it = continut.begin();
while(it!=continut.end())
{
if((*it) == s)
{
it = continut.erase(it);
}
else it++;
}
}
but the == doesn't return me a true value. i also tried to overload the operator == on each shape but same result. what can i do?
This is comparing the memory addresses of two Shape objects:
if((*it) == s) // '*it' is of type `Shape*`
it is not comparing two Shape objects. A further dereference is required to use operator== defined for Shape. However, see What's the right way to overload operator== for a class hierarchy? for a discussion on how to handle operator== for a class hierarchy.
you are comparing the shape pointers addresses and they are different.
you should overload operator ==
here are some examples:
C++ Operator Overloading Guidelines
Operator overloading
Related
class Media {
public:
bool operator==(const Media& other) const {}
bool operator!=(const Media& other) const {}
};
class Book : public Media {
public:
bool operator==(const Book& other) const {} // commenting out this line solves this issue.
bool operator!=(const Book& other) const {}
};
class Game : public Media {
public:
bool operator==(const Game& other) const {}
bool operator!=(const Game& other) const {}
};
int main() {
Book book;
Game game;
bool res = book == game; // doesn't compile.
}
I have these 3 classes and they must have their own == and != operators defined. But then I also have to compare between two siblings using those operators.
I could've written a (pure) virtual function, say, virtual bool equals(const Media& other) const in the base class that subclasses override. And then call that function in the bodies of == and != opertor definition in base class Media. But that feature is gone when I add another bool operator==(const Book& other) const {} in the Book class (the same goes for the Game class too).
Now I want to compare between siblings using those operators and still have all 6 definition in those 3 classes. How do I make it work?
You mentioned in the comments that this form of comparison is an imposed restriction (to compare among siblings of a child type). If its an imposed restriction that you need to somehow perform this with inheritance, then one option is to fulfill the base signature and use dynamic_cast. Note that this is not a clean approach, but it might be the expected solution for this problem if this is some form of assignment.
dynamic_cast uses Runtime Type Information (RTTI) to determine whether an instance to a base class is actually an instance of the derived class. When you use it with a pointer argument, it returns nullptr on failure -- which is easily testable:
auto p = dynamic_cast<const Book*>(&other);
if (p == nullptr) { // other is not a book
return false;
}
// compare books
You can use this along with a virtual function to satisfy the hierarchy. However, to avoid possible ambiguities with c++20's generated symmetric operator==/operator!= functions, it's usually better to do this through a named virtual function rather than the operator== itself in order to prevent ambiguity:
class Media {
public:
virtual ~Media() = default;
bool operator==(const Media& other) const { return do_equals(other); }
private:
virtual bool do_equals(const Media& other) const = 0;
};
class Book : public Media {
...
private:
bool do_equals(const Media& other) const override {
auto* p = dynamic_cast<const Book*>(&other);
if (p == nullptr) { return false; }
return (... some comparison logic ...);
}
...
};
... Same with Game ...
Since we never define operator==(const Book&) or operator==(const Game&), we won't see this shadow the base-class' operator==; instead it always dispatches through the base's operator==(const Media&) -- which is non-virtual and prevents ambiguity.
This would allow a Book and a Game to be comparable, but to return false -- whereas two Book or two Game objects may be compared with the appropriate logic.
Live Example
That said...
This approach is not a good design, as far as software architecture goes. It requires the derived class to query what the type is -- and usually by the time you need to do this, that's an indication that the logic is funky. And when it comes to equality operators, it also leads to complications with symmetry -- where a different derived class may choose to compare things weirdly with different types (imagine a Media that may compare true with other different media; at which point, the order matters for the function call).
A better approach in general is to define each of the respective equality operators between any types that logically require equality comparison. If you are in C++20 this is simple with symmetric equality generation; but pre-C++20 is a bit of a pain.
If a Book is meant to be comparable to a Game, then define operator==(const Game&) or operator==(const Book&, const Game&). Yes, this may mean you have a large number of operator==s to define for each of them; but its much more coherent, and can get better symmetry (especially with C++20's symmetric equality):
bool operator==(const Game&, const Book&);
bool operator==(const Book&, const Game&); // Generated in C++20
bool operator==(const Game&, const Game&);
bool operator==(const Book&, const Book&);
In an organization like this, Media may not even be logical as a 'Base class'. It may be more reasonable to consider some form of static polymorphism instead, such as using std::variant -- which is touched on in #Jarod42's answer. This would allow the types to be homogeneously stored and compared, but without requiring casting from the base to the derived type:
// no inheritance:
class Book { ... };
class Game { ... };
struct EqualityVisitor {
// Compare media of the same type
template <typename T>
bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; }
// Don't compare different media
template <typename T, typename U>
bool operator()(const T&, const U&) const { return false; }
};
class Media
{
public:
...
bool operator==(const Media& other) const {
return std::visit(EqualityVisitor{}, m_media, other.m_media);
}
private:
std::variant<Book, Game> m_media;
};
Live Example
This would be my recommended approach, provided the forms of media are meant to be fixed and not extended.
You might do double dispatch thanks to std::visit/std::variant (C++17):
class Media;
class Book;
class Game;
using MediaPtrVariant = std::variant<const Media*, const Book*, const Game*>;
class Media {
public:
virtual ~Media () = default;
virtual MediaPtrVariant asVariant() const { return this; }
};
class Book : public Media {
public:
MediaPtrVariant asVariant() const override { return this; }
};
class Game : public Media {
public:
MediaPtrVariant asVariant() const override { return this; }
};
struct EqualVisitor
{
template <typename T>
bool operator()(const T*, const T*) const { return true; }
template <typename T, typename U>
bool operator()(const T*, const U*) const { return false; }
};
bool operator ==(const Media& lhs, const Media& rhs)
{
return std::visit(EqualVisitor(), lhs.AsVariant(), rhs.AsVariant());
}
bool operator !=(const Media& lhs, const Media& rhs)
{
return !(lhs == rhs);
}
int main()
{
Book book;
Game game;
bool res = book == game;
}
Demo
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 am writing program which has a multitude of Directed Graph helper functions in order to gain a deeper understanding of C++. One of the central objects is called a Node which has member functions to help with calculating travel distance between nodes. I am trying to gain a better understanding of using C++ templates in OOP design.
Here is a quick snapshot of the Node class
class Node {
friend void swap(Node & first, Node & second) {
using std::swap;
swap(first.name, second.name);
}
public:
Node(std::string val);
Node(const Node & copy);
Node & operator = (Node copy) {
swap(*this, copy);
return *this;
}
bool operator < (Node & rhs) const {
return (size < rhs.size);
}
bool operator > (Node & rhs) const {
return (size > rhs.size);
}
bool insertEdge(Node * dest, int distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
int findTravelDistance(Node * const & toNode) const;
int findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const int size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
protected:
private:
int size;
std::string name;
// Here int represents the weight of the edge. I would like it to be able to be
// declared as an int, float, long, or double etc...
std::map<Node *, int> * travelEdges;
}; // end class
} // end namespace
As I build this class to include more functionality, I find myself struggling with how to make my functions more adaptable. For instance, look at the findTravelDistance functions.
What I would like to do is have the return type representing weight be type agnostic and the ordered map data structure's value to be type agnostic. As it is currently implemented, a user can only declare a type int for the weight. I realize I could embark upon function overloading. But, I feel this would be too redundant and an obvious violation of the DRY principle. If I were to have to change how this function works, I would have to change it for every overload. So my gut instinct tells me I should use C++ templates. Since I am new to templates, I am struggling with where to declare it. If I make my find functions template functions and just return the generic type..
template<class T>
T findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
That will solve my problem there. But, it doesn't fix the issue where the underlying map data structure representing edges can only hold ints. My next thought was to declared a class template..
template<class T>
class Node { ... }
But this also seemed odd to me. This would mean declaration and initialization would look something like
Node<float> * n = new Node<float>("N");
If I were a user of my program, I would not immediately associate Node with the float type representing edge weights.
So what is the best or appropriate usage of a template in this case? Or is using a template even the correct path here? It is possible my class design is flawed to begin with and not very C++'esk. Any feedback here is much appreciated.
This is very clean code :). Welcome to C++!
I believe what you want to do is use a template variable to hold your edge weights. How about something like the following:
using std::swap;
template<class Distance>
class Node {
friend void swap(Node & first, Node & second) {
swap(first.name, second.name);
}
public:
Node(std::string val);
Node(const Node & copy);
Node & operator = (Node copy) {
swap(*this, copy);
return *this;
}
bool operator < (Node & rhs) const {
return (size < rhs.size);
}
bool operator > (Node & rhs) const {
return (size > rhs.size);
}
bool insertEdge(Node * dest, Distance distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
Distance findTravelDistance(Node * const & toNode) const;
Distance findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const Distance size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
private:
int size;
std::string name;
std::map<Node *, Distance> * travelEdges;
}; // end class
As a bonus, I've moved your using declarations to the top of the class. Generally these go at the top of the file. You also might benefit from taking a look at the holy scripture that is the Parashift C++ FAQ, particularly the section on const correctness. Your comparator methods, for example, should have const Node& parameters.
I have a header file where i am declaring a class with a structure within it. Also i am declaring an overloading operator(!=, to compare structures) as member of this class. I am giving the definition of this operator in the cpp file. But i am not able to access the members of the structure
car.h
class car
{
int carsor;
struct model
{
int id;
int mode;
}prev,curr;
bool operator !=(const model& model1);
};
car.cpp
#include "car.h"
bool car::operator !=(const model& model1)
{
if((model1.id==model.id)&&(model1.mode==model.mode))
{
return false;
}
else
{
return false;
}
}
The error i get is this
Error 2 error C2275: 'car::model' : illegal use of this type as an expression
how should i access the the structure members?
if((model1.id==model.id)&&(model1.mode==model.mode)) - model is the name of your class and not your object. Your object is accessible via this or you may omit it altogether inside the class.
Use if((model1.id==prev.id)&&(model1.mode==prev.mode)) to compare with prev or if((model1.id==next.id)&&(model1.mode==next.mode)) to compare with next.
This:
bool car::operator !=(const model& model1)
{
is a method comparing a car to a model. This, however:
bool car::model::operator != (car::model const &other) const
{
return !(*this == other);
}
is a method comparing two models (I've written it here as a method of car::model, but it could be a free function if you prefer.
I've also written it in terms of operator==, because the logic almost always works out easier:
bool car::model::operator ==(car::model const &other) const
{
return (this->id == other.id) && (this->mode == other.mode);
}
These methods would be declared as:
class car
{
struct model
{
int id;
int mode;
bool operator==(model const&) const;
bool operator!=(model const&) const;
// ...
I'm trying to overload the assignment operator and would like to clear a few things up if that's ok.
I have a non member function, bool operator==( const MyClass& obj1, const myClass& obj2 ) defined oustide of my class.
I can't get at any of my private members for obvious reasons.
So what I think I need to do is to overload the assignment operator. And make assignments in the non member function.
With that said, I think I need to do the following:
use my functions and copy information using strcpy or strdup. I used strcpy.
go to the assignment operator, bool MyClass::operator=( const MyClass& obj1 );
Now we go to the function overloading (==) and assign obj2 to obj1.
I don't have a copy constructor, so I'm stuck with these:
class Class
{
private:
m_1;
m_2;
public:
..
};
void Class::Func1(char buff[]) const
{
strcpy( buff, m_1 );
return;
}
void Class::Func2(char buff[]) const
{
strcpy( buff, m_2 );
return;
}
bool Class& Class::operator=(const Class& obj)
{
if ( this != &obj ) // check for self assignment.
{
strcpy( m_1, obj.m_1 );
// do this for all other private members.
}
return *this;
}
bool operator== (const Class& obj1, const Class& obj2)
{
Class MyClass1, MyClass2;
MyClass1 = obj1;
MyClass2 = obj2;
MyClass2 = MyClass1;
// did this change anything?
// Microsofts debugger can not get this far.
return true;
}
So as you can probably tell, I'm completely lost in this overloading. Any tips? I do have a completed version overloading the same operator, only with ::, so my private members won't lose scope. I return my assignments as true and it works in main. Which is the example that I have in my book.
Will overloading the assignment operator and then preforming conversions in the operator== non member function work? Will I then be able to assign objects to each other in main after having completed that step?
You have a couple of obvious mistakes here and there is some confusion about what you are actually trying to achieve. Firstly, the assignment operator operator = is meant to copy the value from one instance to another. The return value of the assignment operator is almost always a non constant reference to the target of the copy, so that you can chain assignments:
Class & operator=(const Class &rhs)
{
// copy the members
return *this;
}
The comparison operator operator == is meant to perform a comparison of two instances. It returns a boolean true if they are equal:
boolean operator==(const Class &rhs) const
{
// check if they are equal
return something;
}
The confusion is why are you trying to copy values around, or maybe assign to the instances in the comparison operator?
Op== isn't the assignment operator. T& Op= (const T&) is.
bool operator==(const T& lhs, const T& rhs) is the operation to compare two Ts. It returns true if lhs is equal to rhs, for whatever definition of "equal" you want to code.
I am guessing that you want to compare the two objects. In that case, you can just overload the operator == in class "Class". You don't need assignment operator.
class Class
{
public:
Class(int i) : m_i(i){}
bool operator==( const Class& rhs)
{
return m_i == rhs.m_i;
}
private:
int m_i;
};
int main()
{
Class t1(10), t2(10);
bool b = (t1 == t2);
}
I am not sure whether I understood the question correctly. But if you trying to check the equality using a non-member function and can't do this only because you can't access the private members of the class, then you can declare the non-member function as a friend function and use it like this:
class Test
{
public:
Test(int i) : m_i(i){}
private:
int m_i;
friend bool operator==(Test& first, Test& second);
};
bool operator==(Test& first, Test& second)
{
return first.m_i == second.m_i;
}
int main()
{
Test t1(10), t2(10);
bool b = (t1 == t2);
}