Reputation: 147
I need to call the base method A::foo() from derived class by pointer.
#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". Is it possible to call A::foo() by pointer to method?
Upvotes: 6
Views: 1046
Reputation: 11
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()
.
So if you want to call base method by pointer, you should make it non-virtual (as @PasserBy mentioned in comments).
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()
Upvotes: 1
Reputation: 846
Well, you can do something similar using some tricks with overwriting the value of this
. You probably should never try to do that though, vtable
pointers aren't meant to be modified by hand.
To do what you described, we need to have the pointer to A's 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.
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
Upvotes: 1