views:

175

answers:

3

I am trying to write a function that will check if an object exists:

bool UnloadingBay::isEmpty() {
    bool isEmpty = true;
    if(this->unloadingShip != NULL) {
        isEmpty = false;
    }
    return isEmpty;
}

I am pretty new to C++ and not sure if my Java background is confusing something, but the compiler gives an error:

UnloadingBay.cpp:36: error: no match for ‘operator!=’ in ‘((UnloadingBay*)this)->UnloadingBay::unloadingShip != 0’

I can't seem to figure out why it doesn't work.

Here is the declaration for class UnloadingBay:

class UnloadingBay {

    private:
        Ship unloadingShip;

    public:
        UnloadingBay();
        ~UnloadingBay();

        void unloadContainer(Container container);
        void loadContainer(Container container);
        void dockShip(Ship ship);
        void undockShip(Ship ship);
        bool isEmpty();

};
+2  A: 

I'm assuming unloadingShip is an object and not a pointer so the value could never be NULL.

ie.

SomeClass unloadingShip

versus

SomeClass *unloadingShip

GWW
Yes it is an object. How can I check if unloadingShip is instantiated or not?
pharma_joe
If UnloadingBay is instantiated, then its unloadingShip object is instantiated as well (even as you are in the UnloadingBay constructor).
EboMike
if "this" (aka the UnloadingBay object) is instantiated, unloadingShip will automatically be instantiated also, because unloadingShip is part of the UnloadingBay object. i.e. the UnloadingBay object and the UnloadingShip object are both part of the same hunk of memory, if you will. It's not like Java where every single object has to be allocated individually.
Jeremy Friesner
Yes I think I am having trouble adapting to pointers and references. I have included the class declaration to clarify.
pharma_joe
+2  A: 

Well, you don't have to write so much code to check if a pointer is NULL or not. The method could be a lot simpler:

bool UnloadingBay::isEmpty() const {
    return unloadingShip == NULL;
}

Plus, it should be marked as "const" because it does not modify the state of the object and can be called on constant instances as well.

In your case, "unloadingShip" is an object of class "UnloadingShip" which is not dynamically allocated (except when the whole class "UnloadingBay" is allocated dynamically). Thus, checking if it equals to NULL doesn't make sense because it is not a pointer.

Vlad Lazarenko
OK I have added the declaration. Thanks!
pharma_joe
+8  A: 

It sounds like you may need a primer on the concept of a "variable" in C++.

In C++ every variable's lifetime is tied to it's encompassing scope. The simplest example of this is a function's local variables:

void foo() // foo scope begins
{  
    UnloadingShip anUnloadingShip; // constructed with default constructor

    // do stuff without fear!
    anUnloadingShip.Unload();
} // // foo scope ends, anything associated with it guaranteed to go away

In the above code "anUnloadingShip" is default constructed when the function foo is entered (ie its scope is entered). No "new" required. When the encompassing scope goes away (in this case when foo exits), your user-defined destructor is automatically called to clean up the UnloadingShip. The associated memory is automatically cleaned up.

When the encompassing scope is a C++ class (that is to say a member variable):

class UnloadingBay
{
   int foo;
   UnloadingShip unloadingShip;
};

the lifetime is tied to the instances of the class, so when our function creates an "UnloadingBay"

void bar2()
{
    UnloadingBay aBay; /*no new required, default constructor called,
                         which calls UnloadingShip's constructor for
                         it's member unloadingShip*/

    // do stuff!
}  /*destructor fires, which in turn trigger's member's destructors*/

the members of aBay are constructed and live as long as "aBay" lives.

This is all figured out at compile time. There is no run-time reference counting preventing destruction. No considerations are made for anything else that might refer to or point to that variable. The compiler analyzes the functions we wrote to determine the scope, and therefore lifetime, of the variables. The compiler sees where a variable's scope ends and anything needed to clean up that variable will get inserted at compile time.

"new", "NULL", (don't forget "delete") in C++ come into play with pointers. Pointers are a type of variable that holds a memory address of some object. Programmers use the value "NULL" to indicate that a pointer doesn't hold an address (ie it doesn't point to anything). If you aren't using pointers, you don't need to think about NULL.

Until you've mastered how variables in C++ go in and out of scope, avoid pointers. It's another topic entirely.

Good luck!

Doug T.
Hey thanks very much, I appreciate it a lot. Pointers are giving me a little trouble to understand, but I'm getting there. Cheers
pharma_joe
I like the "guaranteed" part :-) Especially if some dude decides to throw exception in destructor!
Vlad Lazarenko
@Vlad, when you throw in a destructor, your program is guaranteed to go away so either way the variable goes away :)
Doug T.