- I have a base class and a derived class and a bunch of methods defined as virtual which are overridden in the derived class.
- I have an instance of the derived class assigned to a base pointer "myPointer" so the derived class virtual methods are called.
- Is it possible to "cast" the "myPointer" to a pointer pointing to the actual base instance and hence the base virtual methods are invoked through the new "casted pointer"?.
I know about
myPointer->Base::MyMethod();so that is not what I want. I want to do something like:Base* myPointer = new Derived(); Base* actualBasePointer = (some kind of case) myPointer; actualBasePointer->MyMethod(); // this invokes the base virtual method.
3 Answers
A Base* is a Base*. There is no "variant" that disables virtual dispatch / polymorphism, nor is there a type of cast to give you a different kind of pointer that does so.
Either your functions are virtual or they're not, and it would be really confusing if you could switch that on and off.
Instead, have alternative, non-virtual functions in your class that do what you need. I would recommend that you find a way to make these private to avoid confusion with the existing public virtual functions — generally this means they will be purely for utility/internal purposes. If this means you can't use them for the goal you have in mind, I'd advise reviewing your approach.
Alternatively, stick with the clear and well-known myPointer->Base::MyMethod() — simply knowing about it already doesn't seem like a good reason not to use it.
Comments
Though a derived class object is composed out of its base class objects as far as non-static data members are concerned, the connection between virtual methods to their implementations in the derived class (or the base class, if a method is not overridden) is fixed and tightly coupled with the derived class object. So there is no way to generate a "view to the object's vtable" as if it where that of a Base class object. You can just refer directly to a specific implementation of a method by writing myPointer->Base::MyMethod(), yet this must be expressed explicitly with each call and it will not prohibit dynamic binding if Base::MyMethod() itself calls other virtual methods.
The only way to achieve that the derived class object behaves like a base class object is using object slicing, i.e. assigning a derived class object to an instance (not a pointer or reference) of the base class:
class Base {
public:
int x = 10;
virtual void printX() const {
printInt(x);
}
protected:
virtual void printInt(int i) const {
cout << "Base_printInt: " << i;
}
};
class Derived : public virtual Base {
protected:
virtual void printInt(int i) const override {
cout << "Derived_printInt: " << i;
}
};
int main() {
Derived d;
Base b = static_cast<Base>(d);
b.printX();
}
Output:
Base_printInt: 10
1 Comment
No, you cannot disable virtual dispatch in any such manner.
However I would recommend this design pattern if you do need this behavior.
class StaticBase {
void foo() { /*default implementation*/ }
}
class VirtualBase : StaticBase {
StaticBase& as_base() {
return static_cast<StaticBase&>(*this);
}
virtual void foo() { return StaticBase::foo(); }
}
class Derived : VirtualBase {
virtual void foo() { /* specialization */ }
}
That way you can do things like....
VirtualBase* vbase = new Derived();
vbase->foo(); //derived implementation
vbase->as_base().foo(); //default implementation
actualBasePointer->MyMethod()call would behave differently thanmyPointer->Base::MyMethod()call? What is it you don't like about the latter, that you hope to "fix" with the former?actualBasePointer->MyMethod()behaves differently from what OP intends ifBase::MyMethod()itself calls another virtual method ofBase, which has been overridden inDerived.Derivedidentify, then slicing it is:Base actualBase = *myPointer; actualBase.MyMethod();Won't work for arbitraryBase(e.g. one that is an abstract class).