Sorry, I may be asking a very stupid question.
I don't know why my compiler even has an output from this code below.
All I see in the main function is pointers and declaring names for the strings, and there is no function to actually get an output from this code.
Can someone clarify please.
Well, the reason why there is an output can be found on line 7 (this code is a bit convoluted due to a lack of line breaks, but that's just me). The constructor for a Pet-object sets the name to be the string passed to it, and then calls the function MakeSound(). The constructor for Dog and Cat is an initializer list, that calls the constructor of the parent class (in this case Pet). Thus, it sets the name as well as calls MakeSound() for the respective pet upon being created.
You have a parent class named Pet.
There are two other classes (Cat and Dog) which inherit from Pet.
Which makes sense, because both cats and dogs are pets (in other words, both have the same properties/attributes as pets).
The Pet class has a string member named Name.
The Pet class has a constructor which accepts a string parameter, which is then assigned to Name.
After this assignment, the member function MakeSound() is called.
This is the beef of the program. Each of these three classes has it's own implementation of the MakeSound() method. In each implementation, first the Name of the animal is printed, followed by " the ... says: ...! ...!". This works because Cat and Dog are inheriting Pets members and methods.
Notice, that PetMakeSound() method uses the virtual keyword. This means that child classes (classes that inherit from this parent class) can have their own implementations for the same method. This would not be the case if it was a pure virtual function, in which case the parent method would have no body, and child classes would be required to have their own implementations.
Also notice that Cat and Dog call the Pet constructor in their constructor initialization list. This is not required if the Parent/base class constructor takes no arguments, which will be called implicitly.
Finally, in the main() function, we declare a Cat pointer and a Dog pointer named a_cat and a_dog respectively.
Then, the following happens:
1.) We instanciate a new Cat object on the heap.
2.) We pass a string as a parameter to name the cat.
3.) The pointer returned by the new keyword is assigned to the a_cat pointer.
4.) We do the exact same thing for the a_dog pointer.
Because each objects constructor is called, the MakeSound() method is invoked, which prints out the output you're seeing.