首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++将指针转换为用于虚拟方法调用的基类指针

C++将指针转换为用于虚拟方法调用的基类指针
EN

Stack Overflow用户
提问于 2022-03-28 01:30:55
回答 2查看 82关注 0票数 0

我有以下代码:

代码语言:javascript
运行
复制
struct A 
{
    virtual void foo() {std::cout << "A\n";}
};

struct B : public A 
{
    virtual void foo() {std::cout << "B\n";}
};

void bar(A * a) 
{
    a->foo(); 
}

如果不更改此代码,是否可以将bp指针转换为B,以便调用bar将打印"A"?

代码语言:javascript
运行
复制
int main()
{
    B * bp = new B();
    bar(/* do somethig*/ bp);
    return 0;
}

试过我记忆中的每一个演员:

代码语言:javascript
运行
复制
int main()
{
    B * bp = new B();
    
    bar((A*)bp);
    bar(static_cast<A*>(bp));
    bar(reinterpret_cast<A*>(bp));
    bar(dynamic_cast<A*>(bp));
    return 0;
}
EN

回答 2

Stack Overflow用户

发布于 2022-03-28 02:43:18

您可以围绕B制作一个shim包装器,并将shim的虚拟函数分派给直接调用A::foo();BWrap::foo()调用。

在这个示例中,携带B&成员变量引用实际上没有任何意义,但是对于更有趣的示例,可能有一个用例。

代码语言:javascript
运行
复制
struct BWrap : public A
{
    B& b;
    BWrap(B& bb) : b{bb} {}
    virtual void foo() { b.A::foo(); }
};

int main()
{
    B* bp = new B();
    BWrap bw{*bp};
    bar(&bw);
}
票数 4
EN

Stack Overflow用户

发布于 2022-03-28 01:55:51

如果您坚持A对象是B对象的一个基类子对象,并且根本不修改第一个代码段,那么唯一的解决方案是添加一个更派生的类,它可以覆盖虚拟调用,正如@Eljay在回答中所解释的那样(我在第一次编写这个答案时完全忘记了这个问题)。

其他选项是创建一个完整的A对象,而不是B对象,或者通过使用限定名修改bar以执行不需要虚拟调度的调用:

代码语言:javascript
运行
复制
a->A::foo();

您显示的所有强制转换都具有与隐式转换相同的效果,但reinterpret_cast除外,使用这种方式会导致未定义的行为。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71641560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档