I want to call the base class implementation of a virtual function using a member function pointer.
class Base {
public:
virtual void func() { cout << "base" << endl; }
};
class Derived: public Base {
public:
void func() { cout << "derived" << endl; }
void callFunc()
{
void (Base::*fp)() = &Base::func;
(this->*fp)(); // Derived::func will be called.
// In my application I store the pointer for later use,
// so I can't simply do Base::func().
}
};
In the code above the derived class implementation of func will be called from callFunc. Is there a way I can save a member function pointer that points to Base::func, or will I have to use using in some way?
In my actual application I use boost::bind to create a boost::function object in callFunc which I later use to call func from another part of my program. So if boost::bind or boost::function have some way of getting around this problem that would also help.
When you call a virtual method via a reference or a pointer you will always activate the virtual call mechanism that finds the most derived type.
Your best bet is to add an alternative function that is not virtual.
What you're trying to do unfortunately isn't possible. Pointer-to-member-functions are designed to maintain the virtualness of the function pointed-to.
Your problem is that a member function pointer is not quite the same as a bare function pointer. It actually isn't just a pointer, but a considerably more complex structure, which varies in its details at the level of the compiler implementation. When you invoke it via the syntax (this->*fp)() you are actually calling it on the original object, which causes virtual function dispatch.
One thing that might work is to cast it to a non-method pointer type. This is a little creaky but I think it should work. You still need to pass a Base * but you do it explicitly and the virtual function dispatch is by-passed:
typedef void BasePointer(Base*);
void callFunc()
{
BasePointer fp = (BasePointer *)&Base::func;
fp(this);
}
Update: Ok, no, you can't do it that way. It's illegal, and wouldn't be safe it if it was legal. The C++ FAQ has more on this. But knowing that doesn't solve your problem. The issue is that, pointer-to-object or pointer-to-member if you want to call Base::func through a Base pointer, the object it is pointing must also be a Base. If you can arrange that, then you can use a member function pointer.
Here's another thought, not pretty, but at least workable. Provide a function in Derived, non-virtual, that explicitly calls Base::func. Point to that instead. It won't scale if you need to do this in the general case of lots of different variants of func and callFunc but it will work fine for one method.
Is there any specific reason for doing this via a function pointer?
You should be able to just write:
Base::func();
to call the base class implementation.
In addition to what quark says, a more general remark is that you should use a signal/slot implementation rather than a bare function pointer. Boost has one, there's libsigc and a bunch of others.
What's wrong with this?
(Base(*this).*fp)();
Now if you're satisfied with that, it raises the question of why you're even using a function pointer in the first place. I think some more context might help.
Related
This is related to my thread Member Function Pointers and Inheritance on allegro.cc here.
See the thread on allegro.cc for code examples.
I'm trying to call a base class method through a member function pointer on a virtual method in my WidgetBase class. However it calls the virtual method instead of the base class one. I want to call the base class method through a function pointer, but according to other threads here on stack overflow this is not possible.
So, my question is, what alternatives are there? Lambdas have been suggested, but I'm not sure how to implement that, as I have little experience with C++11 or C++14. Ideas would be welcome.
It is possible to call the base class method if the calling object is actually an instance of the Base class but this causes problems because it involves making a copy of the object I want to call the method on, which defeats the purpose of calling it on the object to begin with.
I was hoping there was some magical cast I could use to implement this, but using static cast to cast to the base class makes a temporary copy of the object, which again, is not what I want.
I want to use this to implement a helper function in my TextDecorator class, which will call a pre-selected state setter function on several different objects contained in the TextDecorator. TextDecorator is derived from WidgetDecoratorBase, which is derived from WidgetBase, which is where the base class functions I want to call reside. This helper function will then be called in the overridden versions of the state setter functions in the TextDecorator class.
Basically, what I want in pseudo C++ code is this :
void TextDecorator::SetFlagState(bool state , void (WidgetBase::*StateSetter)(bool)) {
if (basic_text_widget) {
(basic_text_widget->WidgetBase::*StateSetter)(state);
}
(text_widget_layout->WidgetBase::->*StateSetter)(state);
(this->WidgetDecoratorBase::->*StateSetter)(state);
}
That would then allow me to make my state setting calls in TextDecorator clear and concise, to be called like this :
void TextDecorator::SetEnabledState(bool state) {
SetFlagState(state , SetEnabledState);
}
where SetEnabledState is one of the virtual state setting functions in my WidgetBase class.
Please keep suggestions limited to possible ways to implement this. There has to be a clean concise way to do this in C++.
The simplest solution is a slight refactoring of your base class. Instead of:
class Base {
public:
virtual void foo()
{
// The base implementation of foo().
}
};
Replace it with:
class Base {
public:
virtual void foo()
{
foo_base();
}
void foo_base()
{
// base class implementation of foo.
}
};
The replacement code is 100% logically equivalent. But now, you can obtain a pointer to the foo_base() method, and invoke it directly without any particular difficulty.
I want to call the base class method through a function pointer, but according to other threads here on stack overflow this is not possible.
As far as I know, you can't do that.
The pointer doesn't carry enough information with it.
Invoking a member function through a pointer to a member function is like doing a direct call.
I suspect there doesn't exist any mapping with things like this->B::f() (note that (this->B::*ptr)() is not a valid syntax).
So, my question is, what alternatives are there? Lambdas have been suggested, but I'm not sure how to implement that
Of course, you can work around it easily with a lambda function.
It follows a minimal, working example:
#include<iostream>
#include<utility>
struct B {
virtual void f() { std::cout << "B" << std::endl; }
};
struct D: B {
void f() override { std::cout << "D" << std::endl; }
template<typename F>
void g(F &&f) { std::forward<F>(f)(*this); }
};
int main() {
D d;
d.g([](auto &i){ i.B::f(); });
}
Instead of passing a pointer to a member function, you pass a delegate lambda that does the work under the hood.
The drawback of this approach is that it doesn't work out of the box if the virtual member function is a private one.
As requested in the comments, I'm adding more details.
Let's look over this:
template<typename F>
void g(F &&f) { std::forward<F>(f)(*this); }
In this case, g is a function template that accepts a callable object. The && near to f are there because f is a forwarding reference and it can be used to bind either to an lvalue reference or to an rvalue reference.
I'd suggest to read this article by Meyers, when he also suggested the terms universal reference for the same thing.
The std::forward serves the purpose of forwarding the variable by preserving exactly its type. Note that a variable having type rvalue reference to would be an lvalue reference in the context of g otherwise.
In the article above mentioned this is explained with more details.
Now consider this line of code:
d.g([](auto &i){ i.B::f(); });
We are invoking g using a generic lambda as an argument.
It's not strictly necessary, we could have used this instead:
d.g([](D &i){ i.B::f(); });
Apart for the fact that the type is deduced, the idea is that we receive an instance of a class that derives from B and we call the implementation of f from B on that instance.
Who is demanded to give use such a reference?
Back to the previous snippet:
template<typename F>
void g(F &&f) { std::forward<F>(f)(*this); }
Nite that here we are invoking f (that is our lambda) using *this as an argument (it forms a reference to an object of type D).
That's all.
I'm learning C++ now and I read a lot of materials about using superclass's pointer to point to a subclass' object, especially in the case of (pure) virtual classes. Since I don't have a lot of experience, could anyone help me to understand why we need to do that? Thanks a lot!
You don't need to. You can use a pointer to the derived type if that's what you really want.
The Liskov substitution principle says that we should always be able to use a derived type wherever the base type is expected. The idea is that a derived type should be no more restrictive than its base class. That way, the derived really is-a base type, and can be used wherever the base type would be used. The base type defines the interface and the derived type should meet that same interface. The derived type can augment the interface, if it likes.
The type of pointer that your function should take depends on exactly what you want to be able to accept. If you have a hierarchy with two Widgets, Button and List, for example, then if your function is happy to take any kind of Widget, it should take a Widget*. If the function specifically requires a Button, however, it should take a Button*. The reason for this is that the function probably requires some functionality that only the Button can provide.
When a member function is called through a pointer and the compiler sees that that function is virtual, the compiler ensures that the dynamic type of the object is used to determine which function to call. That is, imagine you have a Widget* parameter but actually pass a pointer to a Button object. The static type of the object is Widget (if the compiler were to only look at the parameter type), but its dynamic type is Button. If you call widget->draw(), where draw is a virtual function, it will see that the dynamic type is Button and ensure that Button::draw is called.
However, I don't recommend using raw pointers in general, so prefer references (Widget&) or smart pointers if you can.
Here's an example:
struct base { virtual void do_stuff(); = 0 };
struct specialization1: base {
void do_stuff() override { std::cout << "doing concrete stuff"; }
};
Consider that you have client code that wants to call do_stuff.
First implementation (this is how not to do it):
void client_do_stuff( specialization1& s ) { s.do_stuff(); }
This function works. If you decide (four months from now) to add to your code base:
struct specialization2: base {
void do_stuff() override { std::cout << "doing other concrete stuff"; }
};
You may want to call void client_do_stuff for an instance of specialization2. You could duplicate client_do_stuff with a specialization2 reference, but that is code duplication and unnecessary.
A better solution would be to change client_do_stuff to take a reference to the base class, and use the same implementation with both specializations.
Second implementation:
void client_do_stuff( base& b ) { b.do_stuff(); }
client code:
specialization1 s1;
specialization2 s2;
client_do_stuff(s1); // works
client_do_stuff(s2); // works
This implementation of client_do_stuff is implemented in terms of the public interface of the base class, instead of a specialization. This makes the function "future-proof" (the principle is sometimes called "program to an interface, not an implementation").
The idea is as follows: An object has the following interface (the pure virtual class). I will hand a concrete object to your code, which adheres to this interface, but the internal details of said object I will keep to myself (encapsulation). Thus your code can make no assumptions on the precise size etc. of the object. Therefore when compiling your code, you have to use pointers or references when manipulating the object.
I was studying Virtual Functions and Pointers. Below code made me to think about, why does one need Virtual Function when we can type cast base class pointer the way we want?
class baseclass {
public:
void show() {
cout << "In Base\n";
}
};
class derivedclass1 : public baseclass {
public:
void show() {
cout << "In Derived 1\n";
}
};
class derivedclass2 : public baseclass {
public:
void show() {
cout << "In Derived 2\n";
}
};
int main(void) {
baseclass * bptr[2];
bptr[0] = new derivedclass1;
bptr[1] = new derivedclass2;
((derivedclass1*) bptr)->show();
((derivedclass2*) bptr)->show();
delete bptr[0];
delete bptr[1];
return 0;
}
Gives same result if we use virtual in base class.
In Derived 1
In Derived 2
Am I missing something?
Your example appears to work, because there is no data, and no virtual methods, and no multiple inheritance. Try adding int value; to derivedclass1, const char *cstr; to derivedclass2, initialize these in corresponding constructors, and add printing these to corresponding show() methods.
You will see how show() will print garbage value (if you cast pointer to derivedclass1 when it is not) or crash (if you cast the pointer to derivedclass2 when class in fact is not of that type), or behave otherwise oddly.
C++ class member functions AKA methods are nothing more than functions, which take one hidden extra argument, this pointer, and they assume that it points to an object of right type. So when you have an object of type derivedclass1, but you cast a pointer to it to type derivedclass2, then what happens without virtual methods is this:
method of derivedclass2 gets called, because well, you explicitly said "this is a pointer to derivedclass2".
the method gets pointer to actual object, this. It thinks it points to actual instance of derivedclass2, which would have certain data members at certain offsets.
if the object actually is a derivedclass1, that memory contains something quite different. So if method thinks there is a char pointer, but in fact there isn't, then accessing the data it points to will probably access illegal address and crash.
If you instead use virtual methods, and have pointer to common base class, then when you call a method, compiler generates code to call the right method. It actually inserts code and data (using a table filled with virtual method pointers, usually called vtable, one per class, and pointer to it, one per object/instance) with which it knows to call the right method. So when ever you call a virtual method, it's not a direct call, but instead the object has extra pointer to the vtable of the real class, which tells what method should really be called for that object.
In summary, type casts are in no way an alternative to virtual methods. And, as a side note, every type cast is a place to ask "Why is this cast here? Is there some fundamental problem with this software, if it needs a cast here?". Legitimate use cases for type casts are quite rare indeed, especially with OOP objects. Also, never use C-style type casts with object pointers, use static_cast and dynamic_cast if you really need to cast.
If you use virtual functions, your code calling the function doesn't need to know about the actual class of the object. You'd just call the function blindly and correct function would be executed. This is the basis of polymorphism.
Type-casting is always risky and can cause run-time errors in large programs.
Your code should be open for extension but closed for modifications.
Hope this helps.
You need virtual functions where you don't know the derived type until run-time (e.g. when it depends on user input).
In your example, you have hard-coded casts to derivedclass2 and derivedclass1. Now what would you do here?
void f(baseclass * bptr)
{
// call the right show() function
}
Perhaps your confusion stems from the fact that you've not yet encountered a situation where virtual functions were actually useful. When you always know exactly at compile-time the concrete type you are operating on, then you don't need virtual functions at all.
Two other problems in your example code:
Use of C-style cast instead of C++-style dynamic_cast (of course, you usually don't need to cast anyway when you use virtual functons for the problem they are designed to solve).
Treating arrays polymorphically. See Item 3 in Scott Meyer's More Effective C++ book ("Never treat arrays polymorphically").
My question is not about calling a virtual member function from a base class constructor, but whether the pointer to a virtual member function is valid in the base class constructor.
Given the following
class A
{
void (A::*m_pMember)();
public:
A() :
m_pMember(&A::vmember)
{
}
virtual void vmember()
{
printf("In A::vmember()\n");
}
void test()
{
(this->*m_pMember)();
}
};
class B : public A
{
public:
virtual void vmember()
{
printf("In B::vmember()\n");
}
};
int main()
{
B b;
b.test();
return 0;
}
Will this produce "In B::vmember()" for all compliant c++ compilers?
The pointer is valid, however you have to keep in mind that when a virtual function is invoked through a pointer it is always resolved in accordance with the dynamic type of the object used on the left-hand side. This means that when you invoke a virtual function from the constructor, it doesn't matter whether you invoke it directly or whether you invoke it through a pointer. In both cases the call will resolve to the type whose constructor is currently working. That's how virtual functions work, when you invoke them during object construction (or destruction).
Note also that pointers to member functions are generally not attached to specific functions at the point of initalization. If the target function is non-virtual, they one can say that the pointer points to a specific function. However, if the target function is virtual, there's no way to say where the pointer is pointing to. For example, the language specification explicitly states that when you compare (for equality) two pointers that happen to point to virtual functions, the result is unspecified.
"Valid" is a specific term when applied to pointers. Data pointers are valid when they point to an object or NULL; function pointers are valid when they point to a function or NULL, and pointers to members are valid when the point to a member or NULL.
However, from your question about actual output, I can infer that you wanted to ask something else. Let's look at your vmember function - or should I say functions? Obviously there are two function bodies. You could have made only the derived one virtual, so that too confirms that there are really two vmember functions, who both happen to be virtual.
Now, the question becomes whether when taking the address of a member function already chooses the actual function. Your implementations show that they don't, and that this only happens when the pointer is actually dereferenced.
The reason it must work this way is trivial. Taking the address of a member function does not involve an actual object, something that would be needed to resolve the virtual call. Let me show you:
namespace {
void (A::*test)() = &A::vmember;
A a;
B b;
(a.*test)();
(b.*test)();
}
When we initialize test, there is no object of type A or B at all, yet is it possible to take the address of &A::vmember. That same member pointer can then be used with two different objects. What could this produce but "In A::vmember()\n" and "In B::vmember()\n" ?
Read this article for an in-depth discussion of member function pointers and how to use them. This should answer all your questions.
I have found a little explanation on the Old New Thing (a blog by Raymond Chen, sometimes referred to as Microsoft's Chuck Norris).
Of course it says nothing about the compliance, but it explains why:
B b;
b.A::vmember(); // [1]
(b.*&A::vmember)(); // [2]
1 and 2 actually invoke a different function... which is quite surprising, really. It also means that you can't actually prevent the runtime dispatch using a pointer to member function :/
I think no. Pointer to virtual member function is resolved via VMT, so the same way as call to this function would happen. It means that it is not valid, since VMT is populated after constructor finished.
IMO it is implementation defined to take address of a virtual function. This is because virtual functions are implemented using vtables which are compiler implementation specific. Since the vtable is not guaranteed to be complete until the execution of the class ctor is done, a pointer to an entry in such a table (virtual function) may be implementation defined behavior.
There is a somewhat related question that I asked on SO here few months back; which basically says taking address of the virtual function is not specified in the C++ standard.
So, in any case even if it works for you, the solution will not be portable.
I'm trying to create a function which is overloaded based on the specialization of its parameter, such as this:
class DrawableObject...;
class Mobile : public DrawableObject...;
class Game
{
AddObject(DrawableObject * object)
{
// do something with object
}
AddObject(Mobile * object)
{
AddObject(dynamic_cast<DrawableObject *>(object));
DoSomethingSpecificForSpecializedClass();
}
};
...but my MS compiler is giving me this error:
error C2681: 'Mobile *' : invalid expression type for dynamic_cast
Both classes have virtual functions. Is this the wrong cast for up-casting in this situation? I have tried with a C-style cast and everything functions as intended. Also, are there any potential pit-falls with this design?
For explicit upcasting, use static_cast.
Your design should work fine. Be aware that calls to AddObject() will be ambiguous if you try to pass an object that can be implicitly converted to both Mobile* and DrawableObject*, such as a pointer to a class derived from Mobile.
As Neil stated, the cast is simply wrong. dynamic_cast<> is for downcasting from base towards derived not the other way around. A better approach is to factor out the common code like:
class Game {
protected:
void commonAddObject(DrawableObject *obj) {
// do common stuff here
}
public:
void addObject(DrawableObject *obj) {
commonAddObject(obj);
// do DrawableObject specific stuff here
}
void addObject(MobileObject *obj) {
commonAddObject(obj);
// do MobileObject specific stuff here
}
};
or to create separate methods for DrawableObject and MobileObject that do not rely on overloading by types. I prefer to steer clear of casting altogether if I can.
The cast is wrong, and completely unecessary - Mobile already is a DrawableObject.
Upcasting is always free and safe. That means you don't need to use a protected dynamic_cast. A static_cast would be the proper way to do this, although a c-style cast will work as well. In reality you should be able to do away with the second AddObject function because if you passed a pointer to a Mobile object into the DrawableObject function it would call the proper function without needing any casting. Unless you are planning on putting specialized functionality in the overloaded function I wouldn't write it.
...or remove your AddObject(Mobile * object) overload entirely. Without that function there, it will be "implicitly casted" to it's base class, and the AddObject(DrawableObject*) function would have been called. There is no need for you to manually add an overload and a cast for each type in your hierarchy.
Edit Code was added, I want to clarify some suggestions about your design.
Either your "Game" class treats all objects uniformly, or it does not. If it does not, there is no point in providing a generic "AddObject" overload that is publicly available - you're already coupled tightly to the individual objects, so you might as well drop it and the charade of a loosely coupled design.. You could still have it as a private helper function, AddObjectInternal. Since it's not an overload, you won't need the cast to disambiguate the call.
If you are or hope to treat all objects uniformly, consider putting such logic that you're currently putting in the AddObject overloads into virtual functions on the object class. Then, you only have one AddObject method, which calls the virtual functions on the object added.