为什么不调用子类方法?

时间:2013-02-18 15:08:01

标签: c++ class polymorphism

我有子类化和使用方法的问题。

我创建了一个类B的实例,并将其存储为指向A的指针。但是当我使用指针调用重载方法时,输出是“A”而不是“B”。为什么呢?

这适用于其他语言,我做错了什么?

#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;
}

4 个答案:

答案 0 :(得分:21)

f()需要在基类A中声明virtual

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

您已经使用过的其他语言可能默认为虚方法,但C ++不支持(不支付您不使用的内容:虚拟方法在调用它们时会产生间接,这意味着它们比正常情况稍慢方法调用)。

通过添加virtual,绑定将推迟到运行时(称为dynamic binding),并且将在类型的值上决定f()函数调用。

因为你没有将函数f()声明为虚拟,所以绑定是静态的(在编译时)并且将使用类型的变量(但不是值)来确定{{1}打电话。因此,在您目前的代码中,f()调用a->f();类的A,因为f()是指向a类的指针。

答案 1 :(得分:6)

为了实现多态行为,基类的方法必须是virtual

因此,在class A中,您需要将void f()更改为virtual void f()

答案 2 :(得分:2)

必须声明该函数virtual才能覆盖它:

#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;
}

答案 3 :(得分:0)

当没有指向基类的指针,但没有指向基类的实际实例时,您可能会遇到此问题(不适用于本问题中的示例)

就我而言,我有一个类Token及其子类Word

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

将它们存储在std::map<string, Token>中并从中检索,我希望以这样的代码调用Word::toString()

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

相反,我每次都打电话给Token::toString()

解决方案::使用像std::map<string, Token*>这样的指针并将所有实例都视为指针 (TBH,我已经讨厌指针了)