C++中的虚函数

3
在下面的C++代码中使用虚函数
#include<iostream>
using namespace std;
class Base{
    public:
    virtual void fun(){
        cout << "Base::fun()called \n";
    }

};

class Child : public Base {
    public:
    void fun() {
        cout << "Child::fun() called\n";
    }

    void door(){
        cout << "Child::door() called \n";
    }
};


int main(){

    Base *base_ptr = new Child();
    base_ptr->fun();
    return 0;
}

我该如何使用base_ptr调用door函数? 这个问题是在一次面试中被问到的。 我想知道是否可能实现。
谢谢您的回复。

在你的Base类声明中添加virtual void door()=0;。或者你不能修改Base吗? - drescherjm
@drescherjm。不,你不能修改Base。 - Zaks
你知道吗,也许这只是一个诡计性问题,旨在了解当你看到OOP和类被如此错误地使用时,你的反应如何。 - Christian Hackl
2个回答

6
< p > (假设无法修改 BaseChild。)

您可以使用 static_castbase_ptr 转换为 Child*

static_cast<Child*>(base_ptr)->door()

只要您确信 base_ptr 指向一个Child实例,这就是安全的。


如果您不知道指针base_ptr所指向的派生实例类型,请考虑使用dynamic_cast

if(auto child = dynamic_cast<Child*>(base_ptr))
{
    child->door();
}

除非编译器成功地将其进行了激进的优化,否则与 static_cast 相比,dynamic_cast 具有额外的运行时开销。


4
使用 dynamic_cast 可能更加合适。 - Fred Larson
1
@FredLarson:在这种特定情况下,没有理由使用dynamic_cast。 - Vittorio Romeo
3
你在回答中已经指出了原因,使用static_cast操作符需要确定 base_ptr 实际上指向了一个 Child 实例。而dynamic_cast允许你确定是否如此。 - Ben Voigt
1
@BenVoigt:对于问题中提出的情况,这总是正确的。我更新了答案,以使其更加通用。 - Vittorio Romeo
2
@FredLarson 是正确的,dynamic_cast 总是更好的选择,因为当代码发生变化且原始假设不再有效时,它更具有抗错误性。只有两种情况下才会优先选择 static_cast:当基类中没有虚函数时,以及当你无法承受 dynamic_cast 的开销,因为它在一个紧密循环中(但你可能可以将 dynamic_cast 放在循环外部)。 - Mark Ransom
显示剩余10条评论

0

由于 Base 没有 door() 方法,你显然不能直接调用 base_ptr->door()

但是,如果你知道 base_ptr 是一个 Child,你可以将其强制转换,然后调用 door()

Child* child_ptr = static_cast<Child*>(base_ptr);
child_ptr->door();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接