Reputation: 315
I have spent a great deal of time programming in Java and a decent amount of time writing c++, but I have run into an issue I haven't been able to solve. In a Java class I can simply write the following,
public void doOperation(object a)
{
if(a != this)
{
set(a); // just some method that sets this.a = object.a
}
doOperation();
}
public void doOperation()
{
this.a = pow(this.a,3);
}
The part I am having trouble implementing in c++ is the if statement where I check if the argument object is equal to this. I have tried this in c++
object::doOperation(object a)
{
if(a != this)
{
set(a);
}
doOperation();
}
object::doOperation()
{
this->a = pow(this->a,3)
}
The error I get reads, "no match for ‘operator!=’ (operand types are ‘object’ and ‘object* const’)". Thanks in advance for anybody who can help!
Upvotes: 2
Views: 5551
Reputation: 145339
In Java most objects are passed around as references. To avoid aliasing problems you may then need to check for reference equality: are these two apparently distinct objects, really distinct, or do the references refer to the same object?
In C++ objects are often passed as values, copying their values. And for values it doesn't make sense to check for object identity. E.g. a function argument passed by value, as in your object::doOperation(object a)
example, will always have an address different from everything else at that point in the program execution (it's freshly allocated).
Still there are some cases where objects are passed by reference (or pointer), and where self-check is appropriate.
For example, a copy assignment operator might go like this:
auto My_class::operator=( My_class const& other )
-> My_class&
{
if( &other != this )
{
values_ = other.values_; // Avoid this work for self-assign.
}
return *this;
}
The self-check can also be crucial for correctness, although with use of standard library containers and smart pointers correctness can usually be ensured without any self-check.
Upvotes: 1
Reputation: 36617
If an object has been passed by value as in
void object::doSomething(object x)
{
// whatever
}
then it is not necessary to compare with this. Even of the caller does
some_object.doSomething(some_object);
the x
is a temporary copy - i.e. so a different object is guaranteed.
If the argument is passed by reference or argument then remember that this
is a pointer and not a reference (unlike Java in which those concepts are entwined), for example;
void object::doSomething(object *x)
{
if (this != x)
{
}
}
and
void object::doSomething(object &x)
{
if (this != &x)
{
}
}
The latter assumes that object
does not have an interfering operator&()
. If that assumption is invalid then, in C++11 use addressof(x)
(where addressof()
is specified in <memory>
. Before C++11, the tricks to get address of x
are a little more indirect (e.g. a sequence of casts).
Personally, I don't do such tests at all. Instead, I simply do
void object::doSomething(object &x)
{
object temp(x);
// do things with temp and *this
std::swap(x, temp);
}
which relies on working copy semantics, but also gives more exception safety. If a class makes the above prohibitive, then that is more usually a problem with class design (better to find another way to avoid the need to compare with this).
Upvotes: 0
Reputation: 16204
You can simply pass "a" by reference, take a pointer to "a" and compare it with "this", like so:
object::doOperation(object & a)
{
if(&a != this)
{
set(a);
}
doOperation();
}
object::doOperation()
{
this->a = pow(this->a,3)
}
This is a standard way that people would e.g. implement copy assignment operators in C++. It's not always done this way, but often the implementation of that will take a const reference to an object, and use a check against "this" to prevent self assignment.
Edit: Let me try to take a broader view, which might be more useful to you.
In Java, objects are implicitly passed around by reference and not by value, and they are garbage collected also, automatically destroyed when no-one needs them anymore.
The closest way to get that kind of semantics in C++ is to pass around std::shared_ptr<A>
when in java you would have passed A
. Then, when you need to compare against this
, you can use the get
method to get a raw pointer from the shared pointer and compare it literally against this. OR, if you use the std::enable_shared_from_this
template when you define your class, you can use shared_from_this
to get a shared_ptr<A>
to this at any point in your member functions, and compare the shared_ptr's directly.
I'm assuming you are using C++11, otherwise you would use boost headers for that stuff.
Note also the stuff about "weak_ptr" which you might need to use if you have cyclic references.
Upvotes: 7
Reputation: 46341
That's because this
is a pointer type in C++. If your function signature would use a pointer as well, it would work:
object::doOperation(object* a)
{
if(a != this)
{
set(a);
}
doOperation();
}
Upvotes: 1