I wrote a function to pass to a third party's class. A static function worked fine until the function needed access to a private member variable to do its work. I can do that using a lambda expression (given that it is converted to std::function either automatically or by casting).
Example:
void classA::doingThings()
{
...
classB::needsHelpToDoAThing(
[&](std::type foo) -> size_t { return myFunction(foo); }
);
...
}
size_t class::myFunction(type foo){
...
type someVar = m_somePrivateMember ...(some work)
...
}
But I don't really understand what I'm doing. Now this other class is using private member variables from a different class. Doesn't this violate encapsulation? Is this a hack or am I missing/misunderstanding a concept?
Encapsulation is the idea that other code doesn't get to poke around in your innards willy-nilly.
Here you created a helper function that can poke around in your innards. This helper function is part of your innards, even if you pass it to someone else.
This no more breaks encapsulation than a member method accessing private data. While it isn't part of the interface of the class explicitly, it is still part of the implementation.
Related
I encountered an issue while trying to do something in the process of learning C++ and I am not sure how to handle the situation:
class Command
{
public:
const char * Name;
uint32 Permission;
bool (*Handler)(EmpH*, const char* args); // I do not want to change this by adding more arguments
};
class MyClass : public CommandScript
{
public:
MyClass() : CommandScript("listscript") { }
bool isActive = false;
Command* GetCommands() const
{
static Command commandtable[] =
{
{ "showlist", 3, &DoShowlistCommand } // Maybe handle that differently to fix the problem I've mentioned below?
};
return commandtable;
}
static bool DoShowlistCommand(EmpH * handler, const char * args)
{
// I need to use isActive here for IF statements but I cannot because
// DoShowlistCommand is static and isActive is not static.
// I cannot pass it as a parameter either because I do not want to
// change the structure of class Command at all
// Is there a way to do it?
}
};
Any help would be greatly appreciated! :)
// Is there a way to do it?
No.
Either pass it as parameter, make it static, or make DoShowlistCommand non-static.
There are two potential answers here:
1. about use of non static items in a static functions:
As said in our previous question/answer, this is not possible, unless you'd have in the static function a specific MyClass object (and use object.isActive). Unfortunately, you can't do this here :
your code comments clearly show that you can't add a MyClass parameter to the function call;
the existing parameters don't suggest that you have already a pointer to parent class object;
it would not be adivsable to use global objects in such a context.
2. about what your're trying to do:
It seems that you want to have the function static, because you want to provide it in a table that maps script-commands to function pointers.
Alternative A
If all the function pointers used in commandtable are members of MyClass, you could think of using a pointer to a member function instead of a pointer to a function. The outside object/function that sets isActive on an object, could then refer the pointer to the member function, on the MyClass object it knows.
Alternative B
Revise the design of your code to implement your script engine by using the command design pattern: it's ideally suited for this kind of problems. It will require some refactoring of your code, but it will be so much more maintenable and extensible afterwards !
I don't think there is any way to do it. Here is why:
A static member function is not attached to any particular object, which means it cannot access other members that are not static, since they are attached to an object.
It doesn't look like you need to make it a static member. If you are sure you do - then pass it as a parameter. For example, make a
bool isActive();
function, and pass an argument from it to that function somewhere when you call this 'problematic' one.
You also could change your member variable to static, but it looks like you need it for EACH object, not one-for-all
How do you pass a member function of a class as a parameter to another member function of another class?
class theSecondClass
{
public:
void theFunctionReceiver(void (theFirstClass::*Function)(void));
{
// This part is wrong. "Operand of * must be a pointer"
(*Function)();
}
}
class theFirstClass
{
public:
theSecondClass * SecondClassInstance;
void theFunctiontoPass(void)
{
printf("It worked \n");
return;
}
void theFunctiontoCall(void)
{
SecondClassInstance->theFunctionReceiver(theFunctiontoPass);
}
};
Take the assumption that theSecondClass and theFirstClass are both made already. I'm calling theFirstClass->theFunctiontoCall() from somewhere.
I don't get it. When I pass it in, isn't it pass in as a pointer?
I've taken a look at several similar threads around, but I don't understand them fully.
I'm using VS 2013, basic compiler.
When you write this statement:
SecondClassInstance->theFunctionReceiver(theFunctiontoPass);
What you presumably meant was:
SecondClassInstance->theFunctionReceiver(&theFunctiontoPass);
Which should give you a compiler warning that it's an unqualified member reference, which would point out to you that what you are actually writing is:
SecondClassInstance->theFunctionReceiver(&theFirstClass::theFunctiontoPass);
You are getting a pointer to a member function on the class definition. The "this" is not implicit or included in the package. The only way you're going to be able to call it without a class instance is if it is static. (In which case it won't type-check as a member function...it will just be an ordinary function pointer.)
If I'm going to pass in a reference to my class, why would I even need to pass it the function? Couldn't I just call it with, in the case of the link, ButtonObj->Buttonfunc();
The only reason you would use pointers to member functions is to get some kind of abstraction, where one piece of code can call a member function it doesn't need to explicitly name. If you're okay with theSecondClass::theFunctionReceiver knowing the name of theFirstClass::theFunctionToPass and the identity of theFirstClass...then sure, just pass a reference to an instance of theFirstClass and call the method explicitly.
You might want a situation where theSecondClass is going to call any one of a number of member functions on theFirstClass with matching signatures...it just doesn't want to hard-code which one. In that case, then passing a pair of a class reference and a member function can be done. You seem to suspect this doesn't come up too often as useful, and you would be right. Every year I have to go back and look up the syntax for how to call pointers-to-members on a class, because it almost never comes up except in StackOverflow questions:
How to call through a member function pointer?
More likely what you want (and what people asking those SO questions actually want) is to separate concerns so that theSecondClass has a hook to execute something, but doesn't need to know about theFirstClass at all. Look into lambdas, std::function, and std::bind for generalized solutions which you may be able to experiment with to your satisfaction.
Here is an example to show you what that would look like to conveniently wrap up the call abstractly into a std::function. It makes a function object on the spot, that captures the enclosing this pointer so that when it is invoked it calls the method on the object:
#include <iostream>
#include <functional>
class theSecondClass {
public:
void theFunctionReceiver(std::function<void()> const & Function) {
Function();
}
};
class theFirstClass {
private:
theSecondClass * SecondClassInstance;
public:
void theFunctiontoPass() {
std::cout << "It worked\n";
}
void theFirstClass::theFunctiontoCall() {
SecondClassInstance->theFunctionReceiver(
[this]() {theFunctiontoPass();}
);
}
};
int main() {
theFirstClass tfc;
tfc.theFunctiontoCall();
}
Note this is C++11, which I suggest using if you're not already. Less convenient notations and mechanisms exist in C++98, though.
This corrects problems with your code that go beyond the issue you mention. Please review writing a Minimal, Complete, Verifiable Example. It should be possible to paste your provided code into a compiler and see only the error you wish to discuss.
This adds semicolons after the ends of class definitions
This removes the semicolon after method declarations when you are supplying bodies in the class
You needed various forward definitions to get it to work as you had it, this doesn't require them
When a function takes no parameters, it's customary to define as void foo() not void foo(void). return; as the last line of a function returning no value is kind of superfluous as well.
Avoid writing new C++ code using printf, learn iostreams
Bias member variables to being private or protected.
On StackOverflow code samples try and keep them short and not need scroll bars; it's best to not give opening braces their own line (most of the time)
While naming is subjective, I'd suggest that giving your class names initial caps is a better idea than giving variables initial caps.
What is the advantage of having a free function (in anonymous namespace and accessible only in a single source file) and sending all variables as parameters as opposed to having a private class member function free of any parameters and accessing member variables directly?
header:
Class A {
int myVariable;
void DoSomething() {
myVariable = 1;
}
};
source:
namespace {
void DoSomething2(int &a) {
a = 1;
}
}
int A::SomeFunction() {
DoSomething2(myVariable); // calling free function
DoSomething(); // calling member function
}
If you prefer making them members, then what if I have a case where I first call a function that is not accessing any member variables, but that function calls another function which is accessing a member. Should they both be member functions or free?
see this question: Effective C++ Item 23 Prefer non-member non-friend functions to member functions
and also C++ Member Functions vs Free Functions
You should prefer free functions, in the extent that it promotes loose coupling.
Consider making it a member function only if it works on the guts of your class, and that you consider it really really tied to your class.
It is a point of the book 101 C++ coding standards, which states to prefer free function and static function over member functions.
Altough this may be considered opinion based, it allows to keep class little, and to seperate concerns.
This answer states: "the reason for this rule is that by using member functions you may rely too much on the internals of a class by accident."
One advantage of a non-member function in a source file is similar to the benefits of the Pimpl idiom: clients using your headers do not have to recompile if you change your implementation.
// widget.h
class Widget
{
public:
void meh();
private:
int bla_;
};
// widget.cpp
namespace {
void helper(Widget* w) // clients will never know about this
{ /* yadayada */ }
}
void widget::meh()
{ helper(this); }
Of course, when written like this, helper() can only use the public interface of Widget, so you gain little. You can put a friend declaration for helper() inside Widget but at some point you better switch to a full-blown Pimpl solution.
The primary advantage of free functions vs member functions is that it helps decouple the interface from the implementation. For example, std::sort doesn't need to know anything about the underlying container on which it operates, just that it's given access to a container (through iterators) that provide certain characteristics.
In your example the DoSomething2 method doesn't do much to decrease coupling since it still has to access the private member by having it passed by reference. It's almost certainly more obvious to just do the state mutation in the plain DoSomething method instead.
When you can implement a task or algorithm in terms of a class's public interface then that makes it a good candidate to make a free function. Scott Meyers summarizes a reasonable set of rules here: http://cpptips.com/nmemfunc_encap
i have made a sample example, in this i'm trying to pass a function as argument i am getting error, could you please help me
typedef void (*callbackptr)(int,int);
class Myfirst
{
public:
Myfirst();
~Myfirst();
void add(int i,callbackptr ptr)
{
ptr(i,3);
}
};
class Mysec
{
public:
Myfirst first_ptr;
Mysec();
~Mysec();
void TestCallback()
{
callbackptr pass_ptr = NULL;
pass_ptr = &Mysec::Testing;
first_ptr.add(2,&Mysec::Testing);
}
void Testing(int a,int b)
{
int c = a+b;
}
};
The type of the callback function you're passing as parameter is not defined as part of a class. You probably should define Testing as static.
You are geting an error because you are pointing to a member function. Pointers to member functions are different. See here:
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1
A member function needs to know what instance it is working with (the this pointer) so it can't be called like any other function. If you moved the callback function out of the class (or made it static, which is similar to moving it out of the class) you could call it like any other function.
A more modern way of doing this is to use functors, e.g. boost::function and something like boost::bind :
C++ Functors - and their uses
how boost::function and boost::bind work
Those can hide the difference between member and global functions.
You are trying to access a member function pointer here, using a simple function pointer typedef, which will not work. Let me explain.
When you write a normal, non-member function (similar to C), the function's code actually exists in a location indicated by the name of the function - which you would pass to a function pointer parameter.
However, in the case of a member function, all you have is the class definition; you don't have the actual instance of the class allocated in memory yet. In such a function, since the this pointer is not yet defined, any reference to member variables wouldn't make sense, since the compiler doesn't have enough information to resolve their memory locations. In fact, member function pointers are not exact addresses; they encode more information than that (which may not be visible to you). For more, read Pointers to Member Functions.
I understand that one benefit of having static member functions is not having to initialize a class to use them. It seems to me that another advantage of them might be not having direct access to the class's not-static stuff.
For example a common practice is if you know that a function will have arguments that are not to be changed, to simply mark these constant. e.g.:
bool My_Class::do_stuff(const int not_to_be_changed_1,
std::vector<int> const * const not_to_be_changed_2)
{
//I can't change my int var, my vector pointer, or the ints inside it.
}
So is it valid to use static member functions to limit access. For example, lets say you have a function
void My_Class::print_error(const unsigned int error_no) {
switch (error_no) {
case 1:
std::cout << "Bad read on..." << std::endl;
break;
//...
default:
break;
}
}
Well here we're not going to be accessing any member variables of the class. So if I changed the function to:
static void My_Class::print_error(const unsigned int error_no) {
switch (error_no) {
case 1:
std::cout << "Bad read on..." << std::endl;
break;
//...
default:
break;
}
}
I'd now get an error, if I inadvertently tried to access one of my private var, etc. (unless I pass myself an instance of my class, which would be purposeful ^_^ !)
Is this a valid technique, similar to proactively making args that should not be changed constants?
What downsides might it have in terms of efficiency or use?
My chief reason for asking is that most of the "static" tutorials I read made no mention of using it in this way, so I was wondering if there was a good reason why not to, considering it seems like a useful tool.
Edit 1: A further logical justification of this use:
I have a function print_error,as outlined above. I could use a namespace:
namespace MY_SPACE {
static void print_error(...) {
...
}
class My_Class {
....
void a(void)
}
}
But this is a pain, because I now have to lengthen ALL of my var declarations, i.e.
MY_SPACE::My_Class class_1;
all to remove a function from my class, that essentially is a member of my class.
Of course there's multiple levels of access control for functions:
//can't change pointer to list directly
void My_Class::print_error(std::vector<int> const * error_code_list) {...}
//can't change pointer to list or list members directly
void My_Class::print_error(std::vector<int> const * const error_code_list) {...}
//can't change pointer to list or list members directly, access
//non-const member vars/functions
void My_Class::print_error(std::vector<int> const * const error_code_list) const {...}
//can't change pointer to list or list members directly, access
//non-static member vars/functions
static void My_Class::print_error(std::vector<int> const * const error_code_list) {...}
//can't change pointer to list or list members directly, access
//member vars/functions that are not BOTH static and const
static void My_Class::print_error(std::vector<int> const * const error_code_list) const {...}
Sure this is a bit atypical, but to lessening degrees so are using const functions and const variables. I've seen lots of examples where people could have used a const function, but didn't. Yet some people think its a good idea. I know a lot of beginning c++ programmers who wouldn't understand the implications of a const function or a static one. Likewise a lot would understand both.
So why are some people so adamantly against using this as an access control mechanism if the language/spec provides for it to be used as such, just as it does with const functions, etc.?
Any member function should have access to the other members of the object. Why are you trying to protect yourself from yourself?
Static members are generally used sparingly, factory methods for example. You'll be creating a situation that makes the next person to work with your code go "WTF???"
Don't do this. Using static as an access-control mechanism is a barbaric abomination.
One reason not to do this is because it's odd. Maintenance programmers will have a hard time understanding your code because it's so odd. Maintainable code is good code. Everybody gets const methods. Nobody gets static-as-const. The best documentation for your code is the code itself. Self-documenting code is a goal you should aspire to. Not so that you don't have to write comments, but so that they won't have to read them. Because you know they're not going to anyway.
Another reason not to do this is because you never know what the future will bring. Your print_error method above does not need to access the class' state -- now. But I can see how it one day might need to. Suppose your class is a wrapper around a UDP socket. Sometime in the middle of the session, the other end slams the door. You want to know why. The last messages you sent or received might hold a clue. Shouldn't you dump it? You need state for that.
A false reason to do this is because it provides member access control. Yes it does this, but there are already mechanisms for this. Suppose you're writing a function that you want to be sure doesn't change the state of the object. For instance, print_error shouldn't change any of the object's state. So make the method const:
class MyClass
{
public:
void print_error(const unsigned int error_no) const;
};
...
void MyClass::print_error(const unsigned int error_no) const
{
// do stuff
}
print_error is a const method, meaning effectively that the this pointer is const. You can't change any non-mutable members, and you can't call any non-const methods. Isn't this really what you want?
Static member functions should be used when they are relevant to the class but do not operate on an instance of the class.
Examples include a class of utility methods, all of which are static because you never need an actual instance of the utility class itself.
Another example is a class that uses static helper functions, and those functions are useful enough for other functions outside the class.
It is certainly fair to say that global scope functions, static member functions, and friend functions aren't quite orthogonal to one another. To a certain extent, this is largely because they are intended to have somewhat different semantic meaning to the programmer, even though they produce similar output.
In particular, the only difference between a static member method and a friend function is that the namespaces are different, the static member has a namespace of ::className::methodName and the friend function is just ::friendFunctionName. They both operate in the same way.
Well, actually there is one other difference, static methods can be accessed via pointer indirection, which can be useful in the case of polymorphic classes.
So the question is, does the function belong as "part" of the class? if so, use a static method. if not, put the method in the global scope, and make it a friend if it might need access to the private member variables (or don't if it doesn't)