C++ 是否可以调用派生对象';从基类向下转换时的虚拟方法?

C++ 是否可以调用派生对象';从基类向下转换时的虚拟方法?,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,鉴于以下类别结构: class Base { virtual void outputMessage() { cout << "Base message!"; } }; class Derived : public Base { virtual void outputMessage() { cout << "Derived message!"; } } 。。输出将是“基本消息!” 是否有任何方法可以强制转换或操纵对象,使派生的outputMessage方

鉴于以下类别结构:

class Base
{
    virtual void outputMessage() { cout << "Base message!"; }
};

class Derived : public Base
{
    virtual void outputMessage() { cout << "Derived message!"; }
}
。。输出将是“基本消息!”

是否有任何方法可以强制转换或操纵对象,使派生的outputMessage方法版本以多态方式调用

编辑:我将尝试显示我追求此目标的原因:

我正在编写移植工具,将其连接到我们的主系统中。因此,我需要访问受保护的成员方法,或者自定义现有的虚拟方法。前者我可以通过定义派生类并向其强制转换对象来静态调用方法。我不能做的是改变我不静态调用的方法的行为(即在代码库的其他地方调用的方法)


我也尝试过直接创建派生类的对象,但由于对通过构造函数传递的对象的操作,这会导致系统的其他部分出现问题。

至少不是以合法的方式。要调用派生类函数,您需要引用派生对象。

否,虚拟函数对所指向对象的实际类型进行操作,在您的情况下,它只是一个简单的


事实上,随着向下投射,你进入了未定义的行为领域。这可能会像多重继承的炸弹一样爆炸,派生类中的vtable与基类中的vtable的偏移量不同。

好吧,即使您将基础对象强制转换为派生对象,在内部,它仍然是基础对象:对象的vtable(函数到RAM指针的实际映射)没有更新。 我不认为有任何方法可以做你想做的事,我也不明白你为什么想做。

在这个问题中,Robs的答案也应该是你问题的答案

没有符合标准的解决方案

您试图做的<强>不可能使用C++标准< <强> > < < /P>的行为。 如果您确实必须这样做作为帮助迁移的短期措施,不要在生产中依赖它,并且可以充分验证行为,您可以进行如下所示的实验

关于你的尝试的讨论 我要展示的是,您采取了错误的方法:简单地将指向base的指针转换为指向派生的指针不会改变对象的vtable指针

得出一个似是而非的结论 解决这个问题,最简单的方法是将对象就地重建为派生对象(“placement”
new
),但这也不起作用,它将重新初始化基类成员

可以创建一个非派生对象,该对象没有数据成员,但具有相同的虚拟调度表条目(即相同的虚拟函数、相同的可访问性私有/受保护/公共、相同的顺序)

更多警告和注意事项 它可能会工作(就像在我的Linux机器上一样),但使用它的风险自负(我建议不要在生产系统上使用)

进一步警告:这只能拦截虚拟分派,当编译器在编译时知道类型时,有时可以静态分派虚拟函数

~/dev cat hack_vtable.cc
// change vtable of existing object to intercept virtual dispatch...

#include <iostream>

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

    std::string s_;
};

struct D : B
{
    virtual void f() { std::cout << "D::f()\n"; }
};

struct E
{
    virtual void f() { std::cout << "E::f()\n"; }
};

int main()
{
    B* p = new B();
    p->s_ = "hello";
    new (p) D();  // WARNING: reconstructs B members

    p->f();
    std::cout << '\'' << p->s_ << "'\n"; // no longer "hello"

    p->s_ = "world";
    new (p) E();
    p->f();  // correctly calls E::f()
    std::cout << '\'' << p->s_ << "'\n"; // still "world"
}

~/dev try hack_vtable   
make: `hack_vtable' is up to date.
D::f()
''
E::f()
'world'
~/dev cat hack\u vtable.cc
//更改现有对象的vtable以拦截虚拟分派。。。
#包括
结构B
{

虚空f(){std::cout你为什么需要这个?事实上,当你不得不做这样的任务时,这说明了设计问题。我将尝试在问题中理解为什么会这样。可能重复@Bo:我不这么认为-链接的问题似乎是问,简单地强制转换到派生对象是否会为additi分配额外的内存这是一个关于虚拟函数的问题,在另一个问题中没有提到。@Tony-好的,另一个问题使用派生的数据而不是派生的函数,但在其他方面代码是相同的(包括类名:-)问题是一样的——你做不到!
~/dev cat hack_vtable.cc
// change vtable of existing object to intercept virtual dispatch...

#include <iostream>

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

    std::string s_;
};

struct D : B
{
    virtual void f() { std::cout << "D::f()\n"; }
};

struct E
{
    virtual void f() { std::cout << "E::f()\n"; }
};

int main()
{
    B* p = new B();
    p->s_ = "hello";
    new (p) D();  // WARNING: reconstructs B members

    p->f();
    std::cout << '\'' << p->s_ << "'\n"; // no longer "hello"

    p->s_ = "world";
    new (p) E();
    p->f();  // correctly calls E::f()
    std::cout << '\'' << p->s_ << "'\n"; // still "world"
}

~/dev try hack_vtable   
make: `hack_vtable' is up to date.
D::f()
''
E::f()
'world'