5

被调用的重写方法的版本取决于您是否关心“通过”基类或“通过”派生类调用函数。但是,我发现如果我调用了一个非重写的方法,并且重写的方法调用了一些重写的函数,那么基类版本仍然被调用,即使我通过指向派生类的指针访问实例。有人可以解释为什么会这样吗?

代码:

class Base {
public:
    void display() {
        foo();
    }
    void foo() {
        cout << "Base.foo()" << endl;
    }
};

class Derived : public Base {
public:
    void foo() {
        cout << "Derived.foo()" << endl;
    }
};

int main() {
    Derived* derived = new Derived();
    derived->display();
    while (true) {}
}
4

4 回答 4

5

即使我通过指向派生类的指针访问实例,仍会调用基类版本。有人可以解释为什么会这样吗?

虽然你通过指向派生类的指针调用方法,但你的方法不是虚拟的,所以使用静态调度,所以直接Base::display()调用Base::foo(),即使它在子类中被覆盖。要实现您想要的行为,您必须使用动态调度,即将您的方法标记为virtual.

class Base {
public:
    void display() {
        foo();
        bar();
    }
    void foo() {
        cout << "Base.foo()" << endl;
    }
    virtual void bar() {
        cout << "Base.bar()" << endl;
    }
};

class Derived : public Base {
public:
    void foo() {
        cout << "Derived.foo()" << endl;
    }
    virtual void bar() {
        cout << "Derived.bar()" << endl;
    }
};

int main() {
    Derived* derived = new Derived();
    derived->display();
}

输出:

Base.foo()
Derived.bar()
于 2015-10-25T20:04:41.100 回答
1

问题是:您没有覆盖任何功能;你隐藏了它的名字

在 C++ 中,只有虚函数(参见C++ FAQ)可以被覆盖。使Base::foo()虚拟会产生预期的结果:(运行代码!

class Base {
public:
    void display() {
        foo();
    }
    virtual void foo() {
        cout << "Base.foo()" << endl;
    }
};

class Derived : public Base {
public:
    void foo() {
        cout << "Derived.foo()" << endl;
    }
};

int main() {
    Derived* derived = new Derived();
    derived->display();
}
于 2015-10-25T20:07:00.857 回答
0
virtual qualifier needs to be used for methods that need to be overridden.
ex:
 class Base {
public:
    void display() {
        foo();
    }
    virtual void foo() {
        cout << "Base.foo()" << endl;
    }
};

class Derived : public Base {
public:
    virtual void foo() {
        cout << "Derived.foo()" << endl;
    }
};

int main() {
    Derived* derived = new Derived();
    derived->display();
    while (true) {}
}
于 2015-10-25T20:00:48.667 回答
0

您没有使用虚拟功能。

类层次结构中的对象有两种类型:它是“真正的”类,以及编译器目前认为它拥有的类。

当你调用一个虚函数时,编译器总是调用属于“真实”类的函数。当你调用一个非虚函数时,编译器调用的函数属于它认为是对象类的类。

在子类中执行代码时,编译器认为 *this 是子类的对象。因此,调用非虚拟函数将调用属于该子类的函数。

于 2015-10-25T20:08:08.497 回答