简体   繁体   English

通过指向派生类的函数调用基本虚方法

[英]Call base virtual method by pointer to function from derived class

I need to call the base method A::foo() from derived class by pointer. 我需要通过指针从派生类调用基本方法A :: foo()。

#include <iostream>
struct A{
    virtual void foo() { std::cout << "A::foo()" << std::endl; }
};

struct B:A{
    virtual void foo() { std::cout << "B::foo()" << std::endl; }
    void callBase(void (A::*f)()){
        (this->*f)();
    }
};

int main(){
    B* p=new B();
    p->callBase(&A::foo);
}

This code output "B::foo". 此代码输出“B :: foo”。 Is it possible to call A::foo() by pointer to method? 是否可以通过指向方法的方法调用A :: foo()?

Well, you can do something similar using some tricks with overwriting the value of this . 那么,你可以使用一些技巧与覆盖的价值做类似的事情this You probably should never try to do that though, vtable pointers aren't meant to be modified by hand. 你可能永远不应该尝试这样做,但vtable指针并不意味着手工修改。

To do what you described, we need to have the pointer to A's vtable . 要做你所描述的,我们需要指向A的vtable Our object p has only pointer to B's vtable , so we need to store second pointer in a field within A's constructor. 我们的对象p只有指向B的vtable指针,所以我们需要在A的构造函数中的一个字段中存储第二个指针。

Here is the code: 这是代码:

#include <iostream>
struct A{
    virtual void foo() { std::cout << "A::foo()" << std::endl; }
    int *a_vtable_ptr;
    // First, save value of A's vtable pointer in a separate variable.
    A() { a_vtable_ptr = *(int**)this; }
};

struct B:A{
    virtual void foo() { std::cout << "B::foo()" << std::endl; }
    void callBase(void (A::*f)()){
        int *my_vtable_ptr = *(int**)this;
        // Then modify vtable pointer of given object to one that corresponds to class A.
        *(int**)this = a_vtable_ptr;
        (this->*f)(); // Call the method as usual.
        // Restore the original vtable pointer.
        *(int**)this = my_vtable_ptr;
    }
};

// Function main() is not modified.
int main(){
    B* p=new B();
    void (A::*f)() = &A::foo;
    p->callBase(f);
}

Output: 输出:

A::foo()

Process finished with exit code 0

Virtual methods are designed to implement polymorphism and pointers to virtual methods supports their polymorphic behavior. 虚方法旨在实现多态,而指向虚方法的指针支持其多态行为。 But you given the possibility to call the base method by explicitly calling p->A::foo() . 但是您可以通过显式调用p->A::foo()来调用base方法。

So if you want to call base method by pointer, you should make it non-virtual (as @PasserBy mentioned in comments). 因此,如果要通过指针调用基本方法,则应将其设置为非虚拟(如注释中提到的@PasserBy)。

Code example: 代码示例:

struct A {
    virtual void foo() { std::cout << "A::foo()" << std::endl; }
    void bar() { std::cout << "A::bar()" << std::endl; }
    void callBase(void (A::*f)()) { (this->*f)(); }
};

struct B : A {
    virtual void foo() { std::cout << "B::foo()" << std::endl; }
    void bar() { std::cout << "B::bar()" << std::endl; }
};

int main()
{
    A* p = new B();
    p->foo();
    p->bar();
    p->callBase(&A::foo);
    p->callBase(&A::bar);
    p->A::foo();
    p->A::bar();
}

Output: 输出:

B::foo()
A::bar()
B::foo()
A::bar()
A::foo()
A::bar()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何通过基类指针调用派生类的虚函数 - How to call virtual function of derived class through base class pointer 使用派生类指针从基类析构函数调用非虚拟基类成员函数是否安全? - Is it safe to call a non-virtual base class member function from the base class destructor using a derived class pointer? 如何从基类构造函数调用派生类虚方法? - How to call derived class virtual method from base class constructor? 如何从基类指针调用派生类方法? - How to call derived class method from base class pointer? 在派生类型的对象上从基类调用虚方法 - Call virtual method from base class on object of derived type 从基调用派生类的隐藏(非虚拟)方法 - Call hidden (non virtual) method of derived class from base 基 class 指针不调用派生 class 方法 - Base class pointer not call the derived class method 如何从 function 调用派生类的方法,期望基本 class 指针? - How can I call a derived class's method from a function expecting the a base class pointer? 从基指针列表循环(OOD)调用派生类方法 - Call derived class method from base pointer list loop (OOD) 为什么允许通过基类的指针调用派生类的私有虚方法? - Why is it allowed to call derived class' private virtual method via pointer of base class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM