Why subclass method isn't called?
Asked Answered
R

4

12

I have problem with subclassing and using methods.

I create an instance of class B and store it as a pointer to A. But when I use the pointer to call the overloaded method, the output is "A" not "B". Why?

This works in other languages, what am I doing wrong?

#include <iostream>
using namespace std;

class A {
public:
    void f() {
        cout << "A";
    }
};

class B : public A {
public:
    void f() {
        cout << "B";
    }
};

int main() {
    A *a = new B();
    a->f();
    return 0;
}
Rodgers answered 18/2, 2013 at 15:8 Comment(2)
declare A's f() method virtual. for to postpone binging at runtime. Otherwise static binging forLacework
yeah because it's not virtualTyrontyrone
T
23

f() needs to be declared virtual in the base class A:

class A {
public:
    virtual void f() {
        cout << "A";
    }
};

The other languages you already worked with may default to virtual methods, but C++ doesn't (don't pay for what you don't use: virtual methods incur an indirection when calling them which means they are slightly slower than normal method calls).

By adding virtual, binding will be postponed to runtime (called dynamic binding) and which f() function call will be decided on the type of the value.

Because you have not declared function f() as virtual, binding is static (at compilation time) and will use the type of variable (but not value) to determine which f() to call. So in your present code statment a->f(); calls the A class's f() because a is pointer to the A class.

Tillich answered 18/2, 2013 at 15:10 Comment(0)
K
6

In order to achieve polymorphic behavior, the method of the base class must be virtual.

So in class A you need to change void f() to virtual void f().

Kissable answered 18/2, 2013 at 15:9 Comment(0)
H
2

The function must be declared virtual to be able to override it:

#include <iostream>
using namespace std;

class A {
public:
    virtual void f() {// Here you must define the virtual.
        cout << "A";
    }
};

class B : public A {
public:
    virtual void f() { //Here the "virtual" is optional, but a good practice
        cout << "B";
    }
};

int main() {
    A *a = new B();
    a->f();
    return 0;
}
Hammers answered 18/2, 2013 at 15:20 Comment(1)
When a subclass provides the implementation of a method that is already defined in the base class, it's method overriding not overloading.Kissable
C
0

You may face this problem when having not a pointers to the base class, but the actual instances of it (not applicable to the example in this question)

In my case, I had a class Token and its subclass Word:

class Token {
   public: virtual string toString() { ... }
}
class Word: public Token {
   public: string toString() { ... }
}

Storing them in std::map<string, Token> and retrieving from it I expected to call Word::toString() in code like this:

std::map<string, Token> words;
words.insert("test", Word(...));
words["test"].toString();

instead I called Token::toString() every time.

Solution: to use pointers like this std::map<string, Token*> and treat all instances as pointers (TBH, I hate pointers already)

Couturier answered 19/10, 2020 at 21:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.