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)
Related
Typically, a standard function is called by
functionName(list of arguments).
Another standard way to call a function of an object is
object.functionName(list of arguments).
Both methods are clear and easy to understand since the function signatures are called in the exact order.
However, when it comes to the below:
A unary operator overloading: classA::operator-(), for example, doesn't take any argument. So when we write object2 = -object1,assuming object2 and object1 are both instances of classA, how does C++ know that it has to call classA::operator-() since we didn't write object2 = object1.operator-()?
A global function that defines the + operation between 2 objects for example Complex operator+(int number, const Complex& c). So when we write answer = 10 + aComplexNumber, how does C++ know which function to call since we didn't write operator+(10, aComplexNumber)?
A classA::operator[] operator overloading: so when we call object[argument]. How does C++ know which function to call since we didn't write object.operator[](argument)?
Edit: thank you all for the suggestions. I have edited my question to make it clearer.
This all depends on the operator.
Class::operator- () only operates on one item, so therefore, it does not need an argument since it can just be a member overloaded operator. (i.e. this will be operated on). This unary operator's return type should be the same as the object:
Class obj1;
obj1 = -obj1; //Calls the unary operator- and then the operator=
Now, let's suppose you want to implement the operator again but have it do operations on 2 Objects. That's where we add two different arguments and make it a non-member overloaded operator. For example: operator-(const Class & lhs, const Class & rhs), this will also most likely return an Class and will be called when you create two Class and subtract one from the other:
Class obj1;
Class obj2;
Class obj3 = obj1 - obj2; //Calls the non-member operator then operator=
Some overloaded operators must be member overloaded operators, such as the assignment operator= (const Object & rhs) and by default, the left-hand-side is this since you are assigning this Object to the rhs.
So again, it depends on the operator. You'll have to be more specific if you want more details on a specific operator.
Struct A
{
int* ptr;
int operator+=(const A& other)
{
// if(ptr == nullptr)
// { DoSomething(); }
// else { ...}
}
...
}
Is it possible to have a template operator+= (on a NON-template Class A) in order to resolve that if statement at compile time?
EDIT: I have a bunch of API's, all with the signature:
A funcX()
{
// lot of A's overloaded operators calls
return A;
}
Now, I need to use those API's with a new type, that shares a lot of members with A and add a new one (a smart pointer).
Since all the A funcX() return by value, I cannot derive my new type from A and call A funcX() with the derived type (slicing).
So my solution is to add a smart pointer to A, and a constructor in A that initializes that pointer.
So now I get to use all the API's, and when A is constructed with its new constructor (that initializes the pointer), I want all the operators to have a different behaviour than the existing one.
I was looking into some templates tricks to avoid the cost of checking the pointer inside each operator, although from the comments it doesn't seem possible to achieve it.
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 doubt whether we can do the following or not.
Suppose I have created two instance of class A i.e. obj1 and obj2 and class A has member function show().
Can I use the following?
(obj1+obj2).show()
If yes, how? If no, why it is not possible?
Yes it is possible, just implement operator+ for A and have it return a class of type A:
#include <iostream>
class A
{
public:
explicit A(int v) : value(v) {}
void show() const { std::cout << value << '\n'; }
int value;
};
A operator+(const A& lhs, const A& rhs)
{
A result( lhs.value + rhs.value );
return result;
}
int main()
{
A a(1);
A b(1);
(a+b).show(); // prints 2!
return 0;
}
You can do it if you overload the + operator in such a way that it takes two arguments of type A and yields an object that has a method named show.
Yes you can use it if you have overloaded the + operator of class A to return an obect of class A.
If obj1+obj2 does return an object that have a show() function member, then yes it's possible.
If not, it is not.
So, it depends on the operator+ function that is used here, that depends on both types of obj1 and obj2.
obj1+obj2 is an expression that have a type, the type of the object returned by the operation, like any expression. Now, once the expression is executed, you have this object. But as here you don't associate it to a name (using assignation for example), it is a "temporary", meaning it will be destroyed at the end of the full expression.
So, if the resulting temporary object's type does provide a show() function then you can call it like you did.
If it don't provide a show() function, then you're trying to call a function that don't exists.
So in any case, the compiler will stop you, it will not be a runtime error.
I would be you, I would setup a minimal test project just to play with those principles.
Write an operator overload for + operator and define the operation you want on that.
In the operator overload for + operator just update the logic you want like adding the individual member variables or concatenating the names etc meaningfully based on your use case
Then you can call That new object.Show() function just like an object calling member function.
Depends on what the result type of obj1+obj2 is and whether .show() is a constant method.
No! The result of (obj1+obj2) isn't object. You may overload "="
and use:
obj3 = obj1 + obj2;
obj3.show();
i have a class like this:
class test
{
vector<expr*> _exprs;
bool cmp(expr* e1, expr* e2);
ExprManager* mg;
}
and the Comparison function is:
bool test::cmp(expr* e1, expr* e2)
{
return exprHight(mg, e1) < exprHight(mg, e2);
}
then when i use the comparison function in sorting the _exprs(in another member function)
sort(_exprs->begin(), _exprs->end(), cmp);
The compiler report:
error: argument of type ‘bool (test::)(void*, void*)’ does not match ‘bool (test::*)(void*, void*)’
How to fix it? Thanks for advance.
The normal way to define a predicate for sorting is as a functor.
Make your class define the operator() to do the comparing, and you can just pass an instance of the class to std::sort.
So really, all you need to do is to define the class like this instead:
class test
{
vector<expr*> _exprs;
bool operator()(expr* e1, expr* e2);
ExprManager* mg;
}
And then you can call sort like this:
sort(_exprs->begin(), _exprs->end(), test());
or, of course, use an existing instance of the test class, instead of constructing a new one. But you just pass in a class instance, and don't need to mention the member function at all.
If the sorting takes place in another member function (it looks that way from your reference to _exprs), write
sort(_exprs->begin(), _exprs->end(), *this);
One thing to note is that std::sort, like most other standard library algorithms, copies the predicate object, and so your predicate class must be able to handle copying safely (which your classes should always do anyway)
In short, the way to achieve this is to follow the "rule of three".
If your class defines a destructor, copy constructor or assignment operator, then it should almost certainly define all three.
If the compiler-generated copy constructor is used, it will simply copy your class' pointer members, so you will have two objects containing pointers to the same object.
If the class has a destructor which calls delete on that pointer, then that ends up being done twice. Which is an error.
If your class is intended to be copyable (and most of the standard library requires this), then you must define appropriate copy constructors and assignment operators to implement it safely (for example, copy the resource pointed to by the pointer, or use a smart pointer instead).
IF your class is not intended to be copyable, then you should define the copy constructor and assignment operators to be private, so that attempts to copy the class will result in a compile-time error, instead of runtime crashes.
You should never ever define a class which can be copied, but doesn't do so correctly. Either define the necessary copy constructor/assignment operator/destructors to handle copying, or make copying impossible by making copy ctor/assignment operator private.
Wrapping pointers to dynamically allocated memory owned by the class in smart pointers is a simple way to get copyability for free.
If the class contains only RAII objects, then you don't need to define a destructor at all, and so the rule of three doesn't require you to define copy constructor and assignment operator either.
You need to make test::cmp() static:
class test {
// ...
static bool cmp( expr * lhs, expr * rhs );
};
Alternatively, if test::cmp() cannot be static for some reason, you need to use (boost:: or std::tr1::) bind() to bind the (implicit) this parameter of cmp():
test * someInstance = this // other // something;
sort( _exprs->begin(), _exprs->end(),
bind( &test::cmp, someInstance, _1, _2 ) );
Use operator() and then pass '*this' as a Predicate to Sort algorithm.
class test
{
vector<expr*> _exprs;
bool operator()(expr* e1, expr* e2);
ExprManager* mg;
}
sort(_exprs->begin(), _exprs->end(), *this);
Whatever you pass as predicate must have public accessibility,