Assume a class like this:
class Speaker {
public:
void (*saySomething)();
}
The point is that we can instantiate that class and call the stored function pointer in order to make it say something (whatever that turns out to be). The background to such an approach is to have the actual function reside in a shared library and Speaker acts as some sort of wrapper class (The function gets resolved in the library and the pointer is assigned to the variable in the class).
Now consider we have another class that extends Speaker:
class ConstantSpeaker : public Speaker {
protected:
std::string message;
void doSpeak();
}
with the method's implementation like this:
ConstantSpeaker::doSpeak() {
std::cout << message << std:endl;
}
Now I want to assign the saySomething pointer in a way so that the call is somehow re-routed to ConstantSpeaker::doSpeak(). This however isn't possible directly as doSpeak() is a member function and saySomething is a pointer to a non-member-function.
Another idea I had was to create doSpeak() as a friend-function of ConstantSpeaker instead. Then the pointer-assignment works fine but now doSpeak() would require the object holding the actual message as an argument in order to be able to access the message.
To me it seems as if there should be a (more or less) straight-forward way of doing this given that I can only ever call Speaker::saySomething when having an instance of a Speaker at hand. Therefore the availability of the corresponding object shouldn't be a problem but still I can't figure out how I have to assign that pointer.
The only solution I could come up with is to add a public virtual Speaker::doSaySomething function whose implementation will call the function pointer (which is then no longer public in order to prevent miss-usage) and that can be overwritten by ConstantSpeaker to call ConstantSpeaker::doSpeak() instead.
Is there another solution to this problem?
Another solution is just to use a standard std::function<void()>, and then it can be still declared as public.
Also, instead of bare function pointer, you can use pointer to member function, but be aware about slicing, when using it inside a base class.
But, I think, the most trivial way of doing this is just by using virtual function, like you've mentioned.
Maybe tell more about your context? What is the problem you are going to solve?
Related
I am relatively new to C++ and I am working on a personal project for practicing where I need to create a class that can take function pointers with different signatures.
The idea is that each instance of the class will store a pointer to a specific function and can call that function whenever I want.
To give a better idea of what I want, let me explain with a little bit more detail what I am trying to do. The project I am working on is a very basic console game and the object I am trying to create is an object that would store details on each location the player can access in the game.
(DISCLAIMER: I know that most of what I describe later is probably an overkill for a basic console game. I can easily make the whole game in a couple of files using just simple functions and I know how to do that. But the idea here is that I wanted to practice more advanced C++ techniques without having to figure out a complex project. So, since I know how to make a basic console game, I thought it would be a good idea to try and figure out how to achieve the same result but with more advanced techniques)
One of the details that I think should be stored is what happens in each location, basically the text that is output to the screen describing what happens and prompting the user to take action.
Since this would be different for each location, I can't just declare and implement a function in the class.
One way of solving this issue is to create a base class with a virtual function and then implement this function in a series of derived classes, each defining a new location.
The problem I have with this approach is that it makes each location a class that can be inherited further and instanced, which I don't need as I will only have 1 instance of each location.
I can of course just create 1 instance of the class, but I wanted to see if there is a way to avoid having to create separate classes for each location.
This why I started thinking of function pointers.
Now, I know I can declare a function pointer and initialise it in a class like that:
class Test
{
public:
Test(void (*p)())
: print{p}
{}
private:
void (*print)();
};
That works fine as long as the function returns void and accepts no arguments.
So, I thought maybe I can do that with a template:
template <typename Function>
class Test
{
public:
Test(Function *p)
: print{p}
{}
Function *print;
};
This actually works well. I can now have a class that accepts different functions with different return types.
I can create instances of the class in the following way:
void print();
Test<void ()> a {print};
However, I have one problem with this approach. Because it is a class template, I can't have a pointer that I want to use to point to instances of Test class regardless of the function that is passed to them.
For instance, if I declare the following pointer:
Test<void ()> *b = &a;
There is no way to re-assign that pointer to another instance of Test class unless the function pointer passed to it also returns void and accepts no arguments. Otherwise, I have to create a new pointer.
Is there a way to avoid that? Is there a better way of achieving what I am looking for than using function pointers?
Thank you very much and sorry for the long message.
There is no way to re-assign that pointer to another instance of Test class unless the function pointer passed to it also returns void and accepts no arguments.
And how would you expect that to work? Each Test has a different signature for its print method. In the example below, if you assigned action2 to action1, then how would it know what to pass to the print function?
void fun1() {}
void fun2(int) {}
void test() {
Test<void()> action1= &fun1;
action1.print();
Test<void(int)> action2= &fun2;
action2.print(42);
}
What you want is really simple, thanks to improvements in C++11: std::function<void()>.
Whenever you need to pass some arguments to the function, you'd use a lambda, potentially with captures:
#include <functional>
void fun1() {}
void fun2(int) {}
using Action = std::function<void()>;
int main() {
class MyObject { public: void doSomething() {} } obj;
Action action1;
action1 = fun1;
action1 = []{ fun2(42); };
action1 = [&obj]{ obj.doSomething(); }; // obj captured by reference
}
So that's pretty much what you should do.
Now of course you may ask "hey, but what if I wanted to implement something like std::function myself"? It's not a trivial task, if you want to get full functionality of std::function, including small object optimization (i.e. std::function usually doesn't allocate unless the functor it wraps is "big").
I wanted to see what can I do if I had a reason to have the each game location using a function that have different return types.
You chose to use a common abstraction, i.e. some class (like Action) that you can always call the same way, and get to do various things. So, what would you like the following code to do?
Action someAction;
int result = someAction();
std::string result = someAction();
Now suppose that e.g. someAction has captured a void() function. What should the code that assigns the "result" to an integer or a string do? And how would you protect from mistakes, e.g. if you really wanted someAction() to return an int, but you accidentally used one that returns nothing?
Remember that the compiler has to generate code for all of the sites where you call someAction, so it needs to know what to do ahead of time, even if you may otherwise ensure that no "incorrect" calls are made.
You could implement a custom Action class on top of std::function that could support std::optional<ResultType> instead of ResultType. That way, if the actual result of the functor wrapped in Action was convertible to that ResultType, you'd get a non-null optional, otherwise the optional would be null. And the list of supported result types would need to be pre-determined, i.e. the compiler wouldn't be able to dynamically add them, but adding a new type should amount to passing an additional type as a template argument, so it'd be easy to support quite many types.
I have a class "EngineObject"
I would like to have a custom function for that class which may vary by instance of that object.
Right now i'm doing it with function pointers like this:
class EngineObject{
public:
bool (*Update)(EngineObject* Me);
bool (*Prep)(EngineObject* Me);
bool (*OnCollide)(EngineObject* Me, EngineObject* Them);
};
As you may have noticed, this requires me to do something quite atrocious. I have to feed the object to its member function... Digusting
it also requires me to write extra getters and setters that I really don't want to be accessible from any other part of the code, just so I can see the "innards" of the EngineObject from functions passed in via function pointer
Is there some way I could write a function that I could apply, per instance of the object, that could access the privates of the object, and without having to pass the object to the function?
FOR CLARITY:
Let's say I want two EngineObjects
EngineObject1 = new EngineObject();
EngineObject2 = new EngineObject();
I'd like to set the update function of 1 to (something) and 2 to (something else)
EngineObject1.Update = &foo;
EngineObject2.Update = &bar;
I cannot simply use virtual functions and inheritance because these functions need to be able to be assigned and re-assigned at run-time.
The problem is that I need access to privates from these functions, and in order to do that i'd need to write public getters and setters for everything, which sort of erases the need for making anything private...
context:
The reason i'm doing this is to allow dynamic type generation at run time without introspection, to maximize what can be done from a scripting interface, and reduce the total number of functions that need to be bound to the scripting interface and reduce the learning curve for users.
Basically, you'd have an EngineObjectTemplate class which specified what all these functions would be for this dynamically generated type, and then the EngineObject would be created using a function in the EngineObjectTemplate class
EngineObjectTemplates may be generated at run time by combining various pre-written C++ functions (Update, Prep, OnCollide). This would be a "type" of sorts.
If a user wishes to write a new update, prep, or oncollide function, they could choose to write and compile it into a DLL file and add it to the project (Which my EXE will read and add to a list of function pointers, which can be referenced by string names in the scripting language to assign to templates and/or therefore engineobjects), or they could script it in the scripting language I choose, which would of course be slower.
Another reason why i'm doing it this way is that i'd like to avoid inheritance because it is HELL to make inherited classes work with the scripting wrapper I plan on using.
What you want to do is not possible because what you are actually asking is essentially:
"How can I make code living outside of a class access private members".
If this was possible without jumping through some ugly, ugly hoops, then it would mean that private is broken.
The only way to access private members of a class is that the class explicitly gives you access to them, either from its interface, or by marking the code as friend as part of its declaration.
Either the members are private, or they are not. You can't have it both ways.
N.B. This is a bit of a lie, as you can do some tricks in some exceptional corner-cases, but these should only be used as a last resort.
You can create a callable object class that overrides the () operator. A base class would provide the template for what the replaceable function receives as parameters with child classes implementing that particular method. Then you declare the callable class as a friend to your owning class. Like the following:
class EngineObject;
class Callable;
class EngineObject
{
private:
int member;
Callable *func;
public:
EngineObject(int m, Callable *f) : member(m), func(f) {}
int Call(int p)
{
return func(p);
}
friend Callable;
};
class Callable;
{
public:
int operator(EngineObject *eo, int param)
{
eo->member = param;
return param;
}
};
In the above, I also further hid the variable function call behind a wrapper so that an outside function doesn't need to pass the object as a parameter as well.
Background
The title probably sounds confusing, so let me explain. First of all, here is a minimal version of my implementation, so you can follow along with the concepts more easily. If you've seen some of Sean Parent's talks, you'll know he came up with a way to abstract polymorphism, allowing code such as this:
std::vector<Drawable> figures{Circle{}, Square{}};
for (auto &&figure : figures) {draw(figure);}
Notice that there are no pointers or anything. Calling draw on a Drawable will call the appropriate draw function on the contained object without the type of the object being easily accessible. One major downside to this is that similar classes to Drawable have to be written for each task. I'm trying to abstract this a bit so that the function does not have to be known by the class. My current solution is as follows:
std::vector<Applicator<Draw>> figures{Circle{}, Square{}};
for (auto &&figure : figures) {figure.apply(Draw{});}
Here, Draw is a functor with an operator()(Circle) and opeator()(Square), or a generic version. In this way, this is also sort of a visitor pattern implementation. If you wanted to also, say, print the name of each figure, you could do Applicator<Draw, PrintName>. When calling apply, the desired function is chosen.
My implementation works by passing a boost::variant of the callable types to the virtual function and having it visit that variant and call the function within. Overall, I would say this implementation is acceptable, but I haven't yet thought much about allowing any number of parameters or a return type, let alone ones that differ from function to function.
Question
I spent days trying to think of a way to have this work without making Applicator a template. Ideally, the use would be more similar to this. For the sake of simplicity, assume the functions called must have the signature void(ObjectType).
//For added type strictness, I could make this Applicator<Figure> and have
//using Figure<struct Circle> = Circle; etc
std::vector<Applicator> figures{Circle{}, Square{}};
for (auto &&figure : figures) {figure.apply(Draw{});} //or .apply(draw); if I can
The problem usually comes down to the fact that the type of the object can only be obtained within a function called on it. Internally, the class uses virtual functions, which means no templates. When apply is called, here's what happens (identical to Sean's talks):
The internal base class's apply is called on a pointer to the base class with the runtime type of a derived class.
The call is dispatched to the derived class, which knows the type of the stored object.
So by the time I have the object, the function to call must be reduced to a single type known within the class that both knows which function to call and takes the object. I cannot for the life of me come up with a way to do this.
Attempts
Here are a couple of failed attempts so you can see why I find this difficult:
The premise for both of the first two is to have a type that holds a function call minus the unknown first argument (the stored object). This would need to at least be templated on the type of the callable object. By using Sean Parent's technique, it's easy enough to make a FunctionCall<F> class that can be stored in a GenericFunctionCall, much like a Circle in a Figure. This GenericFunctionCall can be passed into the virtual function, whereas the other cannot.
Attempt 1
apply() is called with a known callable object type.
The type of the callable object is used to create a FunctionCall<Type> and store it as a type-erased GenericFunctionCall.
This GenericFunctionCall object is passed to the virtual apply function.
The derived class gets the call object and has the object to be used as the first argument available.
For the same reason of virtual functions not being allowed to be templates, the GenericFunctionCall could call the necessary function on the right FunctionCall<Type>, but not forward the first (stored object) argument.
Attempt 2
As a continuation of attempt 1:
In order to pass the stored object into the function called on the GenericFunctionCall, the stored object could be type-erased into a GenericObject.
One of two things would be possible:
A function is called and given a proper FunctionCall<Type>, but has a GenericObject to give to it, with the type unknown outside of a function called on it. Recall that the function cannot be templated on the function call type.
A function is called and given a proper T representing the stored object, but has a GenericFunctionCall to extract the right function call type from. We're back where we started in the derived class's apply function.
Attempt 3
Take the known type of a callable object when calling apply and use it to make something that stores a function that it can call with a known stored object type (like std::function).
Type-erase that into a boost::any and pass it to the virtual function.
Cast it back to the appropriate type when the stored object type is known in the derived class and then pass the object in.
Realize that this whole approach requires the stored object type to be known when calling apply.
Are there any bright ideas out there for how to turn this class into one that doesn't need the template arguments, but can rather take any callable object and call it with the stored object?
P.S. I'm open for suggestions on better names than Applicator and apply.
This is not possible. Consider a program composed of three translation units:
// tu1.cpp
void populate(std::vector<Applicator>& figures) {
figures.push_back(Circle{});
figures.push_back(Square{});
}
// tu2.cpp
void draw(std::vector<Applicator>& figures) {
for (auto &&figure : figures) { figure.apply(Draw{}); }
}
// tu3.cpp
void combine() {
std::vector<Applicator>& figures;
populate(figures);
draw(figures);
}
It must be possible for each TU to be translated separately, indeed in causal isolation. But this means that at no point is there a compiler that simultaneously has access to Draw and to Circle, so code for Draw to call Circle::draw can never be generated.
Let me start by telling that I understand how virtual methods work (polymorphism, late-binding, vtables).
My question is whether or not I should make my method virtual. I will exemplify my dilemma on a specific case, but any general guidelines will be welcomed too.
The context:
I am creating a library. In this library I have a class CallStack that captures a call stack and then offers vector-like access to the captured stack frames. The capture is done by a protected method CaptureStack. This method could be redefined in a derived class, if the users of the library wish to implement another way to capture the stack. Just to be clear, the discussion to make the method virtual applies only to some methods that I know can be redefined in a derived class (in this case CaptureStack and the destructor), not to all the class methods.
Throughout my library I use CallStack objects, but never exposed as pointers or reference parameters, thus making virtual not needed considering only the use of my library.
And I cannot think of a case when someone would want to use CallStack as pointer or reference to implement polymorphism. If someone wants to derive CallStack and redefine CaptureStack I think just using the derived class object will suffice.
Now just because I cannot think polymorphism will be needed, should I not use virtual methods, or should I use virtual regardless just because a method can be redefined.
Example how CallStack can be used outside my library:
if (error) {
CallStack call_stack; // the constructor calls CaptureStack
for (const auto &stack_frame : call_stack) {
cout << stack_frame << endl;
}
}
A derived class, that redefines CaptureStack could be use in the same manner, not needing polymorphism:
if (error) {
// since this is not a CallStack pointer / reference, virtual would not be needed.
DerivedCallStack d_call_stack;
for (const auto &stack_frame : d_call_stack) {
cout << stack_frame << endl;
}
}
If your library saves the call stack during the constructor then you cannot use virtual methods.
This is C++. One thing people often get wrong when coming to C++ from another language is using virtual methods in constructors. This never works as planned.
C++ sets the virtual function table during each constructor call. That means that functions are never virtual when called from the constructor. The virtual method always points to the current class being constructed.
So even if you did use a virtual method to capture the stack the constructor code would always call the base class method.
To make it work you'd need to take the call out of the constructor and use something like:
CallStack *stack = new DerivedStack;
stack.CaptureStack();
None of your code examples show a good reason to make CaptureStack virtual.
When deciding whether you need a virtual function or not, you need to see if deriving and overriding the function changes the expected behavior/functionality of other functions that you're implementing now or not.
If you are relying on the implementation of that particular function in your other processes of the same class, like another function of the same class, then you might want to have the function as virtual. But if you know what the function is supposed to do in your parent class, and you don't want anybody to change it as far as you're concerned, then it's not a virtual function.
Or as another example, imagine somebody derives a class from you implementation, overrides a function, and passes that object as casted to the parent class to one of your own implemented functions/classes. Would you prefer to have your original implementation of the function or you want them to have you use their own overriden implementation? If the latter is the case, then you should go for virtual, unless not.
It's not clear to me where CallStack is being called. From
your examples, it looks like you're using the template method
pattern, in which the basic functionality is implemented in the
base class, but customized by means of virtual functions
(normally private, not protected) which are provided by the
derived class. In this case (as Peter Bloomfield points out),
the functions must be virtual, since they will be called from
within a member function of the base class; thus, with a static
type of CallStack. However: if I understand your examples
correctly, the call to CallStack will be in the constructor.
This will not work, as during construction of CallStack, the
dynamic type of the object is CallStack, and not
DerivedCallStack, and virtual function calls will resolve to
CallStack.
In such a case, for the use cases you describe, a solution using
templates may be more appropriate. Or even... The name of the
class is clear. I can't think of any reasonable case where
different instances should have different means of capturing the
call stack in a single program. Which suggests that link time
resolution of the type might be appropriate. (I use the
compilation firewall idiom and link time resolution in my own
StackTrace class.)
My question is whether or not I should make my method virtual. I will exemplify my dilemma on a specific case, but any general guidelines will be welcomed too.
Some guidelines:
if you are unsure, you should not do it. Lots of people will tell you that your code should be easily extensible (and as such, virtual), but in practice, most extensible code is never extended, unless you make a library that will be used heavily (see YAGNI principle).
you can use encapsulation in place of inheritance and type polymorphism (templates) as an alternative to class hierarchies in many cases (e.g. std::string and std::wstring are not two concrete implementations of a base string class and they are not inheritable at all).
if (when you are designing your code/public interfaces) you realize you have more than one class that "is an" implementation of another classes' interface, then you should use virtual functions.
You should almost certainly declare the method as virtual.
The first reason is that anything in your base class which calls CaptureStack will be doing so through a base class pointer (i.e. the local this pointer). It will therefore call the base class version of the function, even though a derived class masks it.
Consider the following example:
class Parent
{
public:
void callFoo()
{
foo();
}
void foo()
{
std::cout << "Parent::foo()" << std::endl;
}
};
class Child : public Parent
{
public:
void foo()
{
std::cout << "Child::foo()" << std::endl;
}
};
int main()
{
Child obj;
obj.callFoo();
return 0;
}
The client code using the class is only ever using a derived object (not a base class pointer etc.). However, it's the base class version of foo() that actually gets called. The only way to resolve that is to make foo() virtual.
The second reason is simply one of correct design. If the purpose of the derived class function is to override rather than mask the original, then it should probably do so unless there is a specific reason otherwise (such as performance concerns). If you don't do that, you're inviting bugs and mistakes in future, because the class may not act as expected.
I have a an instance of lasse1 and I want to use it in a method of lasse2 , this method is static method, this just doesn't work :
class Lasse2{
......
public :
static void function(void);
Lasse1* obj;
........
};
And now i want to use it like :
void Lasse2::function(void){
obj->dosmt(); // this doesn't work
.........
any idea how can I solve this?
If you want to access an instance member of your class, then you must have an instance of that class. There's no way around this. Your options are:
Make obj a static member. Do this if you intend to have a single obj for all instances of this class.
Remove static from function() so it becomes an instance method.
If you can't do either of those, then you need to find a way to pass an instance pointer to your function. For example, APIs that require a function pointer often have a mechanism for passing pointer-sized data to that function when it's eventually called.
Change your static method to explicitly pass the object pointer:
static void function(Lasse1* obj)
{
obj->dosmt();
}
But before you do, consider what you're really trying to do (and even write another question if you like).
You need an instance of your class to pull that off.
Create one or receive it through other means (function argument, global variable, class static variable, etc)
SLaks said it best: "You can't"
Here's why:
When you declare a member variable (not static, see obj above), you're telling the compiler that each object of type Lassie2 contains a pointer to a Lassie1.
When you declare a method static, that means that it is independent of all the instances (the actual objects) of that class. It doesn't operate on an object.
So inside of Lasse2::function, there's no this, no Lassie2 object for you to get the obj pointer from.