I want to make an argument for one of the member functions optional. When no argument is provided, it would use an member variable.
However, when I tried to compile it it shows
error: invalid use of non-static data member 'Object::initPos'
Just to isolate the problem, I tried defaulting an int type and it compiled fine.
I wonder what is the problem with my code and how I could use a member function as default value.
Thank you for your help!
Object.h
class Object
{
public:
...
void MoveTo(double speed, Point position);
protected:
Point initPos;
Point currPos;
};
Object.c
void Object::MoveTo(double speed, Point position = initPos)
{
currPos = postion;
}
Point.h
class Point
{
...
private:
double x;
double y;
double z;
};
Default argument expressions for a member function can only depend on things that are in class or global scope. The default argument also has to be specified in the method's declaration (i.e. in the header file).
To get around this, you need 2 overloads of your MoveTo method. One that takes 1 argument, and another that takes 2 arguments. The method taking 1 argument calls the other method, passing along the value that you consider as the default.
void Object::MoveTo(double speed)
{
MoveTo(speed, initPos);
}
void Object::MoveTo(double speed, Point position)
{
// Everything is done here.
}
Note that when you make MoveTo(double) call MoveTo(double, Point), it allows you to write the implementation of MoveTo only once, thereby respecting the DRY principle.
Default values are not part of the prototype, i.e. they're resolved by the caller, not by the function itself. So firstly, they have to be visible to the caller. Secondly, they cannot access protected members of the class. (I'm pretty sure you can't even use public members as defaults, but I'm too tired to check.)
To solve the problem, use chained overloads as suggested in other answers.
You can overload your function member like that:
void Object::MoveTo(double speed, Point position) {
....
}
void Object::MoveTo(double speed) {
Point position = this->initPos;
MoveTo(speed, position);
}
Besides overloading, another approach is passing an invalid value as the default value. Then check it inside your function.
void Object::MoveTo(double speed, Point position = InvalidPosition) {
position = (position != InvalidPosition) ? position : initPos;
...
}
Related
I want to make an argument for one of the member functions optional. When no argument is provided, it would use an member variable.
However, when I tried to compile it it shows
error: invalid use of non-static data member 'Object::initPos'
Just to isolate the problem, I tried defaulting an int type and it compiled fine.
I wonder what is the problem with my code and how I could use a member function as default value.
Thank you for your help!
Object.h
class Object
{
public:
...
void MoveTo(double speed, Point position);
protected:
Point initPos;
Point currPos;
};
Object.c
void Object::MoveTo(double speed, Point position = initPos)
{
currPos = postion;
}
Point.h
class Point
{
...
private:
double x;
double y;
double z;
};
Default argument expressions for a member function can only depend on things that are in class or global scope. The default argument also has to be specified in the method's declaration (i.e. in the header file).
To get around this, you need 2 overloads of your MoveTo method. One that takes 1 argument, and another that takes 2 arguments. The method taking 1 argument calls the other method, passing along the value that you consider as the default.
void Object::MoveTo(double speed)
{
MoveTo(speed, initPos);
}
void Object::MoveTo(double speed, Point position)
{
// Everything is done here.
}
Note that when you make MoveTo(double) call MoveTo(double, Point), it allows you to write the implementation of MoveTo only once, thereby respecting the DRY principle.
Default values are not part of the prototype, i.e. they're resolved by the caller, not by the function itself. So firstly, they have to be visible to the caller. Secondly, they cannot access protected members of the class. (I'm pretty sure you can't even use public members as defaults, but I'm too tired to check.)
To solve the problem, use chained overloads as suggested in other answers.
You can overload your function member like that:
void Object::MoveTo(double speed, Point position) {
....
}
void Object::MoveTo(double speed) {
Point position = this->initPos;
MoveTo(speed, position);
}
Besides overloading, another approach is passing an invalid value as the default value. Then check it inside your function.
void Object::MoveTo(double speed, Point position = InvalidPosition) {
position = (position != InvalidPosition) ? position : initPos;
...
}
I have a class with an array who's size is specified in the constructor. The class also stores a pointer to a function that takes a pointer as a parameter which, when called, will be set to point to the array. I also have a "bind" function which sets the function pointer equal to some other function passed in as a parameter. This allows me to bind arbitrary functions who's parameters will contain the array. It looks like this:
template <typename T>
class MyClass{
public:
MyClass(int s) : size(s) { arr = new T[size]; }
MyClass() { delete[] arr; }
virtual inline void bindFunc(void(*func)(T[])) { fn = func; } //types match, ok
inline void callFunc(){fn(arr);}
/*Yes, I know I need a size parameter to correctly
iterate over arr, I took out this info to help make things more clear, just pretend
arr is null terminated and the bound fn function knows how to correctly handle it*/
private:
const int size;
T arr[];
void(*fn)(T[]);
};
This works fine and all, but the point of using arrays (or any container type) was so classes that inherit from MyClass can specify an explicit size. I then planned to (somehow) override the bindFunc function to take a pointer to a function that has an explicit number of separate parameters instead of a pointer to a function with an array of parameters. This is simply to clean up the syntax and make the derived class hide implementation. It would look something like this:
class derived: public MyClass<double> {
public:
derived() : MyClass(2) {}
inline void bindFunc(void(*func)(double, double)) { fn = func; } //error, type mismatch, obviously
};
The error occurs where fn = func because fn is a pointer to a function that takes an array(pointer) as a parameter and func is a pointer to a function that takes 2 doubles as parameters. This is the crux of the problem that I do not know how to fix.
Of course, in this snippet I slimmed down the code a bit to only contain the relevant parts and renamed everything to better portray my problem. If it helps, the original purpose of the class was to store state information passed in from GLFW's callback functions. The derived class(es) were supposed to hold scroll and mouse position info respectively (1 element for scroll position, 2 elements for mouse X/Y position, hence the array who's size is set in the derived class' constructor.) The base class also had functions for calculating other things such as deltas that any other imaginable type of variable input would find useful, hence the hierarchy abstraction. This was all meant to simplify input handling and would've looked something like this when being utilized:
void mouse_callback(GLFWwindow*, double, double);
glfwSetCursorPosCallback(window, mouse_callback);
MyClass *MouseInput = new derived;
void mouseFunction(double x, double y){ //takes 2 doubles instead of array of doubles of size 2
if(x > 0.5)
//do something
if(y < 0.5)
//do something else
}
void main(){
MouseInput->bindFunc(mouseFunction);
MouseInput->callFunc();
}
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
MouseInput->setInfo(xpos, ypos);
/*this function is not shown in the code above, but it basically sets
MouseInput->arr's variables and calls a base class' calculation function
to calculate extra info such as the aforementioned deltas*/
}
I'm not sure if what I want is possible, but I'm interested in learning more about it or a more correct design pattern. I've tried fiddling around with <functional> functions, but I couldn't come up with anything myself. It feels like there would be a feature to the language that would make something like this possible, which is why I cared to type up this question to begin with.
Most of what I experiment with in C++ is for learning and I know my methods might be a little insane for what I'm trying to accomplish, but the hope is it will lead to being a better programmer. Thanks for your insight in advance!
If you use std::function instead of raw function pointers, you can use a lambda to translate the arguments in any way you want:
template <typename T>
class MyClass{
std::function<void(T[])> fn;
public:
virtual inline void bindFunc(void(*func)(T[])) { fn = func; } //types match, ok
virtual inline void bindFunc(void(*func)(T, T)) {
fn = [func](T args[]) { func(args[0], args[1]); }; }
for more flexibility, you can make the func argument a std::function as well
I got the following class:
class Foo {
private:
static float scale;
public:
static float setScale(float scale);
};
When I am trying to implement setScale like this:
float Foo::setScale(float scale) {
this->scale = scale;
return scale;
}
It throws an error:
Invalid use of 'this' outside of a non-static member function.
I really don't get this since my function is marked static.
I saw some related questions but it didn't answer my question.
So how can I fix this?
I know I can change the names and don't use this but there probably is a solution for this?
EDIT: Also when I implement the function inside the class it still throws the same error.
A static member function is not part of the class. In other words, there is only one instance of it. Notice how you access them using the scope resolution operator(Foo::setscale(1.f);), instead of the member reference operator(Foo.setscale(1.f)), because they are not members of instances of the class.
class Foo
{
public:
void DoSomething();
};
In this example, if I create a Foo f and call f.DoSomething(), what happens is that the compiler actually transforms DoSomething() into DoSomething(Foo* this) where this is the address of f.
However, since static member functions are not part of the class, the compiler does not transform them to take in a this pointer.
P.S. So why have static member functions? For one, you can limit the scope of the function to the class it is declared in.
Thank you for reading.
this pointer is not there in static member functions of class. Change the definition as follows:-
float Foo::setScale(float s) {
Foo::scale = s;
return s;
}
Change the function definition the following way
float Foo::setScale(float scale) {
Foo::scale = scale;
}
static member functions have no implicit parameter this.
In the note of paragraph #2 of section 9.4.1 Static member functions of the C++ Standard there is explicitly written that
2 [ Note: A static member function does not have a this pointer
(9.3.2). —end note ]
Also you have to define the function as having return type void because at least you are returning nothing from the function.
void Foo::setScale(float scale) {
Foo::scale = scale;
}
This is probably something elementary, I have a function from one class (called cell) with identifier woo_func_ptr taking a pointer to function of type void with no arguments (void (*void_ptr)(void)) (which I typedef). In another class, I have an object of cell and I use the method woo_func_ptr. It won't allow me to, I get the error in the above title. If these two functions were not embedded inside a class, they would work fine
typedef void (*void_ptr)(void);
double WOO{0};
struct cell {
void woo_func_ptr(void_ptr jo)
{
jo();
}
};
class woosah
{
public:
void woo_func()
{
WOO+=rand();
std::cout << WOO << std::endl;
};
void run()
{
// other stuff
temp_cell.woo_func_ptr(woo_func);
// yet more stuff
}
cell temp_cell;
};
First of all pointer to woosah member function should be declared as
typedef void (woosah::*void_ptr)(void);
and then compiler would complain that it needs to see woosah definition while parsing this statement.
If you let compiler parse class woosah first by moving it up then it will complain that type cell is not defined (since it is contained within woosah). That wil still not solve your problem because of cyclic dependency while parsing.
One way is to solve cyclic dependency is by making temp_cell a pointer to cell instance and have it contained within woosah.
Also note, the syntax to call member function is by using .* or ->*
void run()
{
// other stuff
temp_cell->woo_func_ptr(temp_cell->*woo_func); // assuming temp_cell is pointer to some cell instance
// yet more stuff
}
http://msdn.microsoft.com/en-us/library/b0x1aatf(v=vs.80).aspx shows similar errors and their fixes.
A member function is not like a regular function. That's why there's a seperate "pointer to member function" type. It's because member functions are passed the implicit this pointer.
In fact, the standard even limits (severly) the casting of pointer to member function.
That's the source of your error.
You could use a static class function...
Change
void woo_func()
to
static void woo_func()
This will of coarse may not be what you want if you are trying to access data members of a particular object.
Member functions are kind of special and should not be treated as normal functions.
I have a class:
class A {
void test_func_0(int);
void run();
typedef void(A::*test_func_t)(int);
struct test_case_t{
test_func_t test_func;
} test_case[100];
};
Now I want to call test_func() inside run():
void A::run()
{
test_case[0].test_func = &test_func_0;
test_case[0].*(test_func)(1);
}
The last line of my code, doesn't work(compile error), no matter what combination I try.
Use this:
void A::run()
{
test_case[0].test_func = &A::test_func_0;
(this->*(test_case[0].test_func))(1);
}
Notice that you had 2 errors. The first one was how you formed the member-function-pointer. Note that the only way to do it is to use &ClassName::FuncName regardless of whether you're at class scope or not. & is mandatory too.
The second is that when you call a member via a member function pointer, you must explicitly specif y the object (of type A in your case) on which to call the member function. In this case you must specify this (and since this is a pointer we use ->* rather than .*)
HTH
Use:
(this->*test_case[0].test_func)(1);
Member function call using pointer-to-member-function:
test_case[0].test_func = &A::test_func_0; //note this also!
(this->*test_case[0].test_func)(1);
Demo : http://www.ideone.com/9o8C4