#include <iostream>

using namespace std;

class Player
{protected:
int health;
int mana;
public:
	
	Player :: Player()
	{
		health = 0;
		mana = 0;
	}
	Player :: Player(int Health, int Mana)
	{
		health = Health;
		mana = Mana;
	}
	int GetHealth()
	{
		return health;
	}
	int GetMana()
	{
		return mana;
	}
	void SetHealth(int Health)
	{
		health = Health;
	}
	void SetMana(int Mana)
	{
		mana = Mana;
	}
	~Player()
	{}


};

int main()
{
	Player *player1 = new Player();
	Player player2(10,20);

	cout << player1 -> GetHealth() << "\n" << player2.GetHealth();

	return 0;
}

Alright, I'm trying to familiarize myself with the class system within C++ and I'm running into an odd problem.

The above code gets me the health of player1 and player2, however, this was after a bit of researching as my first attempt attempted to get player1's health by doing

...
Player player1();
Player player2(10,20);
cout << player1.GetHealth()<< "\n" << player2.GetHealth();
...

The above snippet won't compile as it says player1 needs to declare a class, but if removed player2's health works fine.

My questions are:

1. why does the void constructor not work when initialized this way, but the overloaded constructor does?
2. When a pointer is declared

Player *player1 = new Player();

where is it pointing to? Does it create a memory address not attached to a variable where Player() is initialized?

Think I'm not understanding new as you can't declare

Player player1 = new Player();

as new Player() is a pointer type.

3. What exactly is ->? I noticed it was used in some code when calling functions tied to a variable whose class needs internal functions to be called. However, exactly what it is I wasn't entirely sure of. Google didn't bring up too much meaningful info on it.

The first problem is in your class definition. The scope operator( :: )is only used when your class is declared in one place (like a .h header file) and the functions are defined in another place (like a .cpp source file). When you are declaring and defining a function in one place, using the :: operator is incorrect. The class should be declared/defined in one place like so:

class SomeClass
{
    SomeClass()
    {
        // Some initialization here
    }

    SomeClass( int someVal )
    {
        // Some initalization here
    }
};

If you want to split the class declaration and definition, proceed like so:

// Declaration of class.  Probably appears in a .h file
class SomeClass
{
    SomeClass();
    SomeClass( int someVal );
};

// Definition of class functions.  Probably appears in a .cpp file
SomeClass::SomeClass()
{
    // some initialization here
}

SomeClass::SomeClass( int someVal )
{
    // some initialization here
}
  1. When a pointer is declared

where is it pointing to? Does it create a memory address not attached to a variable where Player() is initialized?

Think I'm not understanding new as you can't declare

as new Player() is a pointer type.

The key here is understanding the new operator. Whenever you use the new operator, you are asking for dynamic allocation. Basically, the program reserves some space in the heap for the new object instance, initializes it using the provided constructor, and returns a pointer to the location in memory of the new object. When you have some code like this:

SomeClass* somePointer = new SomeClass();

The variable somePointer is given the memory location of the newly created instance of SomeClass. This code won't work

SomeClass someInstance = new SomeClass();

Because the new operator returns a pointer. You cannot assign a pointer to an instance of SomeClass just like you can't assign a double to an int.

  1. What exactly is ->? I noticed it was used in some code when calling functions tied to a variable whose class needs internal functions to be called. However, exactly what it is I wasn't entirely sure of. Google didn't bring up too much meaningful info on it.

The -> operator is very similar to the . operator. The difference is, when you are working with a pointer, you use -> instead of .

Suppose you have a pointer to a dynamically allocated instance of SomeClass. If you want to use one of the methods of SomeClass you would use the -> operator:

SomeClass someInstance();
someInstance.someMethod();

SomeClass* somePointer = new SomeClass();
somePointer->someMethod();

One final note. Whenever you dynamically allocate an instance of any class, you must deallocate the instance using the delete operator. If you do not delete your dynamically allocated objects, your program will have a memory leak. In other words, the memory reserved for the instance of your object will never be freed up for other uses. Local instances of variables have their memory freed up when the variable goes out of scope (like returning from a function). Dynamically allocated instances must be manually freed:

int someFunction()
{
    SomeClass someInstance();  // Local instance.
    someInstance.someMethod();
    return 0;  // Memory for someInstance is automatically freed up
}

void someOtherFunction()
{
    SomeClass* somePointer = new SomeClass();  // Dynamically allocated instance
    somePointer->someMethod();
    delete somePointer;   // Free up memory used by the dynamically allocated instance
    return 0;
}

If you do not use the delete operator, every time you called someOtherFunction, the available memory in the heap would decrease as it became cluttered with unused SomeClass instances.

Hope this helped!

Very informative. Very much appreciated, also.

At the end you mention every time it calls someOtherFunction available memory would be decreased. You mean every time a dynamic allocation is created and not deleted right? The way that's worded has me questioning if I call a function within a dynamically allocated class I could have problems.

Also that raises the question for me. Is there any benefits to dynamic allocation vs normal allocation performance wise?

other than not having to initialize an object in one call than it's pointer in another of course.

Very informative. Very much appreciated, also.

At the end you mention every time it calls someOtherFunction available memory would be decreased. You mean every time a dynamic allocation is created and not deleted right? The way that's worded has me questioning if I call a function within a dynamically allocated class I could have problems.

Also that raises the question for me. Is there any benefits to dynamic allocation vs normal allocation performance wise?

other than not having to initialize an object in one call than it's pointer in another of course.

You are correct with your first assumption. Any time you don't deallocate a dynamically allocated object, you lose some memory from the heap. Calling a function inside of a dynamically allocated class creates no memory leak intrinsically, so that is completely safe.

Generally, dynamic allocation has benefits when you are dealing with large objects. The stack has only a limited amount of memory available, and it is reserved for objects created within a closed scope { any code between curly braces }. The stack should mainly be used for local native data types like ints, doubles, bools, and strings. If you are going to create a large array, or a large object, you should probably dynamically allocate it. There is the additional advantage that a dynamically allocated object persists even after you leave the scope where it is created. This can be useful because you only need to keep track of its pointer (memory address) instead of managing the whole object. Consider this code:

int func1()
{
   SomeClass* somePointer = new SomeClass();
   someMethod( somePointer );
}

void someMethod( SomeClass* somePointer )  // <-- No copy in
{
    // do something with somePointer that modifies the underlying SomeClass instance
}   // <-- No copy out

int func2()
{
    SomeClass someInstance();
    someInstance = someOtherMethod( someInstance );
}

SomeClass someOtherMethod( SomeClass someInstance )  // <-- copy in
{
    //  modify someInstance
    return someInstance;  // <-- copy out
}

You can see that for the first method, we only have to pass the pointer to the instance instead of copying the whole object into the function. Then, when we are done, we don't have to return anything because the instance was modified in place. However, for the second instance, we have to copy all the data from someInstance into the function, modify that copy of the instance, and then return the instance which again copies its data back into the original instance. For large objects, the copy-in/copy-out approach is very inefficient. Of course, with c++, the copy-in/copy-out problem can be alleviated by passing objects by reference. But, that is a lesson for another day.

Dynamic allocation is very useful, and it is very powerful when used correctly. It should be used any time you are allocating large objects, or objects that need to survive beyond the current scope. If you use dynamically allocated objects, be sure to delete them! Also remember that the pointer is invalid after you delete the object it points to!

Good luck!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.