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

时间:2017-12-26 06:58:50

标签: c++ inheritance polymorphism function-pointers

我需要通过指针从派生类中调用基本方法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);
}

此代码输出“B :: foo”。是否可以通过指向方法的方法调用A :: foo()?

2 个答案:

答案 0 :(得分:1)

好吧,你可以用一些技巧覆盖this的值来做类似的事情。你可能永远不应该尝试这样做,vtable指针不应该手工修改。

要做你所描述的,我们需要指向A的vtable。我们的对象p只有指向B vtable的指针,所以我们需要在A的构造函数中的字段中存储第二个指针。

以下是代码:

#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);
}

输出:

A::foo()

Process finished with exit code 0

答案 1 :(得分:1)

虚拟方法旨在实现多态性,指向虚方法的指针支持其多态行为。但是您可以通过显式调用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(); } 来调用基本方法。

因此,如果你想通过指针调用base方法,你应该将它设置为非虚拟(如注释中提到的@PasserBy)。

代码示例:

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

输出:

s=df.groupby('DueDate',as_index=False).size().to_frame('number').reset_index()
s.DueDate=s.DueDate.shift(-1).fillna('10/31')
s
Out[251]: 
  DueDate  number
0    6/30       3
1    7/31       2
2    9/30       2
3   10/31       1
s.DueDate.repeat(s.number)
Out[252]: 
0     6/30
0     6/30
0     6/30
1     7/31
1     7/31
2     9/30
2     9/30
3    10/31
Name: DueDate, dtype: object
df['Nextduedate']=s.DueDate.repeat(s.number).values
df
Out[254]: 
   ID Document  Date DueDate Nextduedate
0   1      ABC  1/31     1/1        6/30
1   1      ABC  2/28     1/1        6/30
2   1      ABC  3/31     1/1        6/30
3   1      ABC  4/30    6/30        7/31
4   1      ABC  5/31    6/30        7/31
5   1      ABC  6/30    7/31        9/30
6   1      ABC  7/31    7/31        9/30
7   1      ABC  8/31    9/30       10/31