New to virtual methods

I am working through Sam's Teach Yourself C++ For Linux In 21 Days. Yes, it's an OLD book (Copyrighted 2000) but I HAVE it and the concepts seem relevant. I'm having a problem. I can't figure out this one. Today,I'm typing in a program from the book, but it's not giving me the correct output. pDog->Speak SHOULD be outputting Woof!, not Mammal speak! Why isn't it working?

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
//Listing 11.8 - Using virtual methods
//2020-08-25
#include <iostream>
class Mammal
{
   public:
      Mammal(): itsAge(1) { std::cout << "Mammal constructor...\n"; }
      virtual ~Mammal() { std::cout << "Mammal destructor...\n"; }
      void Move() const { std::cout << "Mammal moves one step.\n"; }
      virtual void Speak() { std::cout << "Mammal speak!\n"; }
   protected:
      int itsAge;
};
class Dog : public Mammal
{
   public:
      Dog() { std::cout << "Dog constructor...\n"; }
      virtual ~Dog() { std::cout << "Dog destructor...\n"; }
      void WagTail() const  { std::cout << "Tail wagging...\n"; }
      void Speak() const { std::cout << "Woof!\n"; }
      void Move() const { std::cout << "Dog moves five steps.\n"; }
};
int main()
{
   Mammal *pDog = new Dog;
   pDog->Move();
   pDog->Speak();
   return 0;
}

OUTPUT:

1
2
3
4
5
6
michael@caitlyn 11 $ ./listing11.8 
Mammal constructor...
Dog constructor...
Mammal moves one step.
Mammal speak!
michael@caitlyn 11 $ 
Your Move() function is not virtual.
Your Speak() function is not const-qualified in your base class, but is const-qualified in your sub class.
read the warnings
foo.cpp|20 col 12| warning: 'Dog::Speak' hides overloaded virtual function [-Woverloaded-virtual]
foo.cpp|10 col 20| note: hidden overloaded virtual function 'Mammal::Speak' declared here: different qualifiers (unqualified vs 'const')


to make it a compile time error
https://en.cppreference.com/w/cpp/language/override (c++11)
void Speak() const override { std::cout << "Woof!\n"; }
foo.cpp|20 col 26| error: non-virtual member function marked 'override' hides virtual member function
foo.cpp|10 col 20| note: hidden overloaded virtual function 'Mammal::Speak' declared here: different qualifiers (unqualified vs 'const')
Last edited on
Thank you for pointing out that my base class Speak() method was not const. I corrected that in my program and it is running correctly now.
its not that old books are totally wrong, they usually are not, so long as you understand that they can be wrong in places (due to language changes) and they can (and often do) present things that we have better ways to solve (language has added a ton since then).
It isnt that old. 3/4 of my books date from the late 80s/early 90s, because I never throw anything away I guess...

the stuff you are doing here is pretty much unchanged.
Last edited on
Maybe this makes more sense than Sam's:

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
58
59
60
61
62
#include <iostream>
class Mammal
{
protected:
    int no_steps{-99};
    std::string sound{"???"};
    
public:
    Mammal(){ std::cout << "Mammal constructor...\n"; }
    virtual ~Mammal() { std::cout << "Mammal destructor...\n"; }
    virtual void Move() const { std::cout << "Moves " << no_steps << " steps.\n"; }
    virtual void Speak() { std::cout << sound <<'\n'; }

};

class Dog : public Mammal
{
public:
    Dog() { std::cout << "Dog constructor...\n";
        no_steps = 5;
        sound = "Woof woof";
    }
    ~Dog() { std::cout << "Dog destructor...\n"; }
    
    void WagTail() const  { std::cout << "Tail wagging...\n"; }
};

class Cat : public Mammal
{
public:
    Cat() { std::cout << "Cat constructor...\n";
        no_steps = 8;
        sound = "Meow meow";
    }
    ~Cat() { std::cout << "Cat destructor...\n"; }
    
    void Scratch() const  { std::cout << "Scratching ...\n"; }
};



int main()
{
    Mammal m;
    m.Speak();
    m.Move();
    
    Dog *pDog = new Dog;
    pDog->Move();
    pDog->Speak();
    pDog->WagTail();
    
    Cat *pCat = new Cat;
    pCat->Move();
    pCat->Speak();
    pCat->Scratch();
        
    delete pDog;
    delete pCat;
    
    return 0;
}


Mammal constructor...
???
Moves -99 steps.
Mammal constructor...
Dog constructor...
Moves 5 steps.
Woof woof
Tail wagging...
Mammal constructor...
Cat constructor...
Moves 8 steps.
Meow meow
Scratching ...
Dog destructor...
Mammal destructor...
Cat destructor...
Mammal destructor...
Mammal destructor...
Program ended with exit code: 0
PS It doesn't make (common) sense to go to all the trouble of designing an inheritance scheme and then declaring a Mammal and then creating it as a new Dog.
Topic archived. No new replies allowed.