1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| class Base { protected : int m_nValue; public : Base( int nValue) : m_nValue(nValue) { } const char * GetName() { return "Base" ; } int GetValue() { return m_nValue; } }; class Derived: public Base { public : Derived( int nValue) : Base(nValue) { } const char * GetName() { return "Derived" ; } int GetValueDoubled() { return m_nValue * 2; } }; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| int main() { using namespace std; Derived cDerived(5); cout << "cDerived is a " << cDerived.GetName() << " and has value " << cDerived.GetValue() << endl; Derived &rDerived = cDerived; cout << "rDerived is a " << rDerived.GetName() << " and has value " << rDerived.GetValue() << endl; Derived *pDerived = &cDerived; cout << "pDerived is a " << pDerived->GetName() << " and has value " << pDerived->GetValue() << endl; return 0; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| int main() { using namespace std; Derived cDerived(5); // These are both legal! Base &rBase = cDerived; Base *pBase = &cDerived; cout << "cDerived is a " << cDerived.GetName() << " and has value " << cDerived.GetValue() << endl; cout << "rBase is a " << rBase.GetName() << " and has value " << rBase.GetValue() << endl; cout << "pBase is a " << pBase->GetName() << " and has value " << pBase->GetValue() << endl; return 0; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| #include <string> class Animal { protected : std::string m_strName; // We're making this constructor protected because // we don't want people creating Animal objects directly, // but we still want derived classes to be able to use it. Animal(std::string strName) : m_strName(strName) { } public : std::string GetName() { return m_strName; } const char * Speak() { return "???" ; } }; class Cat: public Animal { public : Cat(std::string strName) : Animal(strName) { } const char * Speak() { return "Meow" ; } }; class Dog: public Animal { public : Dog(std::string strName) : Animal(strName) { } const char * Speak() { return "Woof" ; } }; int main() { Cat cCat( "Fred" ); cout << "cCat is named " << cCat.GetName() << ", and it says " << cCat.Speak() << endl; Dog cDog( "Garbo" ); cout << "cDog is named " << cDog.GetName() << ", and it says " << cDog.Speak() << endl; Animal *pAnimal = &cCat; cout << "pAnimal is named " << pAnimal->GetName() << ", and it says " << pAnimal->Speak() << endl; Animal *pAnimal = &cDog; cout << "pAnimal is named " << pAnimal->GetName() << ", and it says " << pAnimal->Speak() << endl; return 0; } |
pAnimal->Speak()
calls Animal::Speak() rather than the Dog::Speak() or Cat::Speak() function.
1
2
3
4
5
6
7
8
9
| void Report(Cat &cCat) { cout << cCat.GetName() << " says " << cCat.Speak() << endl; } void Report(Dog &cDog) { cout << cDog.GetName() << " says " << cDog.Speak() << endl; } |
1
2
3
4
| void Report(Animal &rAnimal) { cout << rAnimal.GetName() << " says " << rAnimal.Speak() << endl; } |
cAnimal.Speak()
will call Animal::Speak() instead of the derived version of Speak().
1
2
3
4
5
6
7
8
| Cat acCats[] = { Cat( "Fred" ), Cat( "Tyson" ), Cat( "Zeke" ) }; Dog acDogs[] = { Dog( "Garbo" ), Dog( "Pooky" ), Dog( "Truffle" ) }; for ( int iii=0; iii < 3; iii++) cout << acCats[iii].GetName() << " says " << acCats[iii].Speak() << endl; for ( int iii=0; iii < 3; iii++) cout << acDogs[iii].GetName() << " says " << acDogs[iii].Speak() << endl; |
1
2
3
4
5
6
7
| Cat cFred( "Fred" ), cTyson( "Tyson" ), cZeke( "Zeke" ); Dog cGarbo( "Garbo" ), cPooky( "Pooky" ), cTruffle( "Truffle" ); // Set up an array of pointers to animals, and set those pointers to our Cat and Dog objects Animal *apcAnimals[] = { &cFred, &cGarbo, &cPooky, &cTruffle, &cTyson, &cZeke }; for ( int iii=0; iii < 6; iii++) cout << apcAnimals[iii]->GetName() << " says " << apcAnimals[iii]->Speak() << endl; |
apcAnimals[iii]->Speak()
will call Animal::Speak() instead of the proper derived class version of Speak().