#include <iostream>
#include <vector>
using namespace std;
// Animal attribute/property is common between Cow and Dog, hence this is the interface
// that contains pure virtual functions of the property that is common to Cow and Dog
// Since this is pure abstract class (since it has a pure virtual function), this class
// cannot be instantiated.
class Animal
{
public:
virtual void Speak() const = 0;
};
// Note:
// You can have an implementation of a pure virtual function.
// A derived class can explicitly call the base class implementation (if access permissions are allow it)
// by using a fully-scoped name (by calling Animal::Speak(), if Animal::Speak() is public or protected (i.e. not private).
// The use case can be when there's a more-or-less reasonable default behavior, but the class
// designed wants that sort-of-default behavior to be invoked only explicitly.
// It can also be the case what you want derived classes to always perform their own work but also be able to call a common set of functionality.
// The other use could be for the case when you want to create a pure abstract class, but it does not have a pure virtual function.
// In that case you can make the destructor a pure abstract method and create the implementation for the destructor.
// Note that even though it's permitted by the language, it's not something that I see commonly used
// (and the fact that it can be done seems to surprise most C++ programmers, even experienced ones).
void Animal::Speak() const
{
cout << "Make some noise" << endl;
}
class Cow : public Animal
{
public:
void Speak() const;
};
void Cow::Speak() const
{
cout << "Moo" << endl;
}
class Dog : public Animal
{
public:
void Speak() const;
};
void Dog::Speak() const
{
cout << "Woof" << endl;
}
void Speak(const Animal& animal) // 1. Since we are passing a const reference, this can only call a const member function.
{ // So we will have to make Animal::Speak() const and in turn Cow::Speak() and Dog::Speak() const
animal.Speak(); // 2. Passing a non const reference will let you modify Animal
} // 3. Passing by value will lead to object slicing
int main(int argc, char *argv[])
{
Cow myCow;
Dog myDog;
vector<Animal*> animalVec; // You can't instantiate abstract classes, thus a vector of abstract classes can't work.
// You can however use a vector of pointers to abstract classes.
// Also storing by value i.e. vector<Animal> animalVec; will lead to object slicing
animalVec.push_back(&myCow);
animalVec.push_back(&myDog);
for(vector<Animal*>::iterator iter = animalVec.begin(); iter != animalVec.end(); ++iter)
{
Speak(**iter);
}
system("PAUSE");
return EXIT_SUCCESS;
}
Output:
Moo
Woof
Press any key to continue . . .
No comments:
Post a Comment