I am currently working on overloading the == operator for my linked list. I have the operator in my header set up like the following:
class sqrlst
{
public:
std::vector<int> vlist;
bool operator == (iterator const & rhs )
{
return this->iter == rhs.iter;
};
I then created a method in my header file with the following code
void test()
{
bool flag;
if (vlist.begin()==vlist.begin())
{
flag=true;
}
};
};
However when this method is called it does not go to my overloaded == operator function when it hits the if statment. When I put the debug point on the overload function it says that the line will not be reached.
Any tips or suggestions are greatly appreciated. Thanks!
EDIT: vlist is a list of ints.
Well, std::vector member functions begin() and end() returns iterator of type std::vector<T>::iterator, or `std::vector<T>::const_iterator, depending on whether the vector object is const or non-const. Whatever it is, the iterator type is not defined by you. Overloading == in your class sqrlist does nothing. The overload == should be a member of vector's iterator class, which you're not allowed to edit.
Also note that vector's iterator class has already overloaded == and != operators. So when you compare iterators using ==, it is invoking a member function of vector's iterator class.
Related
I create a two pointer object of a class 'myclass'
myclass *obj1,*obj2;
can I compare these two objects using comparison operator and pointer expression i.e *obj1==*obj2
If yes, how does it happen?
If not, why isn't his allowed?
If yes, how does it happen?
If not, why isn't his allowed?
In short the answer will be yes if you have defined a suitable operator == function for comparing myclass instances and no if you have not defined a suitable operator == function.
There are two ways to declare an operator == function - as a member function of the MyClass class or as a non-member function (sometimes called a global function or free function).
Declaring a MyClass member function might look something like this...
class MyClass
{
public:
bool operator == (const MyClass &rhs) const
{
bool result{ false };
// calculate result;
return result;
}
// ... etc ...
};
Given the statement if (*obj1 == *obj2) the member function above would be called on the *obj1 instance (i.e., this would refer to *obj1) while the *obj2 instance would be passed as the argument to the parameter rhs.
Alternatively, the equality comparison operator for MyClass could be declared as a non-member (aka global) function...
bool operator == (const MyClass &lhs, const MyClass &rhs)
{
bool result{ false };
// calculate result;
return result;
}
In this case, given the statement if (*obj1 == *obj2) the function above would be called with the *obj1 instance passed as the argument to the lhs parameter and the *obj2 instance passed as the argument to the rhs parameter.
You cannot declare both a member function and a non-member function operator == using the same signature. The compiler wouldn't be able to decide which one to call!
Whichever technique you use to declare an operator == function, the "calculate result" code can be absolutely anything that makes sense for your particular class, so long as it returns true or false.
Typically you would compare the various members of the two objects and return true if those members held the same values. But you might not compare all members. Consider, for example, the following Book class...
class Book
{
public:
std::string Title;
std::string Author;
std::string Isbn;
// ... etc ...
};
You might decide that operator == should return true only if the two instances have equal ISBN values because different editions of a book like The Hitchhiker's Guide To The Galaxy should be considered different. Alternatively you might decide that two Book instances are equal if they have the same Title and Author because paperback and hardback editions of the Guide might have different ISBNs but they're still (in some sense) the same book.
Finally(!) it should be noted that while the sample code above uses const MyClass & as the type for the rhs parameter C++ does not require that the rhs parameter be the same type as the lhs parameter.
Normally it would be of course, and defining an operator == function that compared two dissimilar types would be likely to confuse readers and could cause problems for programmers using your class. But, as is often the case, if you think you know what you are doing, C++ won't get in your way.
If you'd like to read more about comparison operators you might find http://en.cppreference.com/w/cpp/language/operator_comparison interesting.
Yes, this will work, but only if you've overloaded the == operator for your class. If you have, then == will invoke the appropriate operator== method, which implements the equality test for your class. In other words, it's up to you to define what equality means for your class.
== operator on pointers will compare their numeric address and hence determine if *obj1 and *obj2 points to the same object or not.
bool operator==(const myclass &obj2); // in this method, see if obj2 is equal to *this.
The code you are suggesting will work only if myclass defines operator==.
And as Jeremy Friesner pointed out, you need to beware of invalid pointers, in particular the value NULL (or nullptr).
So what you really want is:
if ((obj1 != nullptr) && (obj2 != nullptr( && (*obj1 == *obj2)) ...
I would also recommend changing those identifiers to ptr1 and ptr2, as "obj1" and "obj2" would imply to the average reader that they are objects rather than pointers to objects. Or myclsptr1 and myclsptr2, as an indication to the reader of what sort of thing they point to. Or, better yet, names that indicate what their purpose is in this part of the program.
can I compare these two objects using comparison operator and pointer expression i.e *obj1==*obj2
Synactically speaking, you can do that only if the operator is defined for the class. You can do that by overloading the operator== function, which can be a member function or a non-member function.
It will work at run time only if obj1 and obj2 point to valid objects.
If obj1 and obj2 point to valid objects, *obj1 == *obj2 will work just like if you had
MyClass o1;
MyClass o2;
and used o1 == o2
1.Pointer to a class is similar-to pointer to a Structure where if you want to compare you have to access and compare each and every member.
2.You can compare obj1==obj2(which compares address) but if you want to compare two objects *obj1==*obj2 you have to overload "==" operator in your "myclass" like this:::
bool operator==(const myclass& b) {//Compare methods or variables of both objects and return result bool(true/false)
I have understood that we have to write the operator overloading function for < operator when we have using the key as struct since the map uses the strict week ordering it has to compare before inserting in to map.
Hope my understanding is correct by reading from here.
consider the following snippet
struct Node
{
int a;
};
// This is not called
bool operator< (const Node &p_node1,const Node &p_node2)
{
printf("\nCALLED OPERATOR OVERLOADING");
return true;
}
int main()
{
using namespace std;
map<Node,int> my_map;
Node n1;
n1.a=55;
my_map[n1]=2; // operator overloading should be called
return 0;
}
And the issue is operator overloading function not called?
EDIT:
From the answer below, After adding the one more pair to container operator overloading is called.
But why it is called three times specifically, what is compared here?
When the map is empty, the comparator does not need to be invoked because there is nothing to compare against to.
You are inserting the only element in an empty map and so the comparison operator is never called. Try having more than one element in my_map.
Have atleast 2 elements in map for comparison operator to be called.
Node n1;
n1.a=55;
my_map[n1]=2; // operator overloading should be called
Node n2;
n2.a=55;
my_map[n2]=3;
See below modified example code.
http://ideone.com/iGY9Xa
I have a vector of pointers to objects QActionDonald and I'm trying to find the object containing the highest expectedvalue_. I have overloaded the operator< and I'm using the max_element method to obtain an iterator to the highest value but i always receive the end value which is not correct.
QActionDonald.h:
class QActionDonald
{
public:
double expectedvalue_;
bool operator < (const QActionDonald& other) const;
};
QActionDonald.cpp:
bool QActionDonald::operator< (const QActionDonald& other) const
{
return expectedvalue_ < other.expectedvalue_;
}
otherClass:
std::vector<QActionDonald*> *actionList = qValueDictionary[stateKey];
std::vector<QActionDonald*>::iterator it =
std::max_element(actionList->begin(), actionList->end());
Of course it's not, because your container has pointers, not objects.
For it to be used, you'll need std::vector<QActionDonald> or, if that's not subject to change, to provide a custom comparator to std::max_element that applies the correct logic (i.e. compare objects, not pointers).
I'm having some trouble keeping objects in a vector, and I think I need to do something with the operators.
std::vector<Foo> vec;
Foo a = Foo();
vec.push_back(a);
...
if(std::find(vec.begin(), vec.end(), a) < vec.end()) {
// Found
} else {
// Not found
}
Foo needs operator== to compile, I do this
bool Foo::operator==(const Foo& rhs) {
return this == &rhs;
}
But from what I understand, vec.push_back, is going to make a copy of the Foo object, so my == will return false.
Hence, whenever I get to the searching, it is never found.
What's the right thing to do here? I'm hoping to avoid switching to a vector of pointers.
Change the implementation of Foo::operator== to compare the member variables of Foo for equality instead of checking identity. For example:
bool Foo::operator==(const Foo& rhs) const {
return get_a() == rhs.get_a()
&& get_b() == rhs.get_b(); // and so on
}
Note that this can also be a const function since it should not modify any member variables and should be usable on const instances of Foo.
Your operator== implies that identity is defined by its location in memory, but the fact that you are appending values to a vector and hoping for equality says that identity is NOT defined by location.
If for some reason you don't have an identity definition based on any other members, you can add a unique identifier to your Foo objects, can compare that identifier in your code:
bool operator==(const Foo &rhs)
{
return this->m_id == rhs.m_id;
}
There is really nothing you can do, std::vector<> (or rather most standard containers) makes copies on insertions. If equality of two Foo objects is really defined by their addresses being equal the only thing you can do is to store pointers in the std::vector<>. If you want to store pointers in the std::vector<> I'd recommend storing smart-pointers instead like std::shared_ptr<>, std::unique_ptr<>.
If Foo's is too heavy to copy you can make Foo Move-only in C++11 or you can make it move only in C++03 using boost::containers::vector and boost::move.
Probably it is just easier to change the operator==() to compare the member variables instead.
I have a problem with overloading of the < operator.
I have this class:
WordEntry.h:
class WordEntry
{
public:
WordEntry(string word);
~WordEntry();
bool operator<(const WordEntry otherWordEntry);
string getWord();
private:
string _word;
};
WordEntry.cpp(I removed constructor & destructor):
string WordEntry::getWord()
{
return _word;
}
bool WordEntry::operator<(WordEntry otherWordEntry)
{
return lexicographical_compare(_word.begin(),_word.end(),otherWordEntry.getWord().begin(),otherWordEntry.getWord().end());
}
Everything is fine when I'm using it in main.cpp like that:
WordEntry w1("Der");
WordEntry w2("das");
if (w1.operator<(w2)) {
cout << "w1 > w2";
}
else
{
cout << "w2 > w1";
}
But when I call sort() on a vector with WordEntry objects, I'll get the error message
Invalid operands to binary expression ('const WordEntry' and 'const
WordEntry')
and it points to stl_algo.h.
Does anyone knows what's going on here?
Right now the argument to < is const but the member is not. This means a < comparison between 2 const WordEntry& objects will fail because it can't bind to <. You need to make the member and the argument both const
bool operator<(const WordEntry& otherWordEntry) const;
bool WordEntry::operator<(const WordEntry& otherWordEntry) const {
...
}
Note: As pointed out in the comments you should also pass WordEntry by reference
string WordEntry::getWord()
bool WordEntry::operator<(WordEntry otherWordEntry)
{
return lexicographical_compare(_word.begin(),
_word.end(),
otherWordEntry.getWord().begin(),
otherWordEntry.getWord().end());
}
The getWord member function creates a copy of the internal member attribute and returns the copy. Two consecutive calls to getWord will return two different std::string instances with the same contents, but they are different objects none the less. The lexicographical_compare function requires that the first and second arguments are iterators into the same container, and similarly the third and fourth arguments. In your case you are passing iterators into different containers (string), which will be compared inside the function and will yield undefined behavior.
The simplest solution is have getWord return a const reference to the internal std::string, in that way, the iterators will both refer to the internal object in the right hand side object.
As others have also mentioned, you should pass the WordEntry by const reference, and the operator< should be const, to improve the code. But the issue in your implementation is the mixture of iterators from different container.
Use a const reference for the rvalue and make the method const to promise the compiler you won't change the object.
bool operator<(const WordEntry& otherWordEntry) const
{
// comparison
}
You also don't need to explicitly call the operator.
Once defined for the WordEntry object you can do this:
if (w1 < w2) { // etc }
Since you aren't using a custom comparing predicate you could just use the std::string::operator<:
return _word < otherWordEntry._word;
David makes an excellent point on returning the internal member by value. If you want to use lexicographical_compare with an accessor instead of the _word member directly (which can as you're in the class scope) then you should define it like so:
const string& getWord() const { return _word; }