I have a class that I want to have a default function to be pointed to when constructing without parameters, but I want that functionality to change when a function is passed in with one of the parameters.
I'm getting the error "a value of type "int (MyClass::*)(int myVar)" cannot be assigned to an entity of type "MyClass::funcptr""
but it seems like the defaultFunction should match the definition to the function pointer.
I fought with this for a while and I'm having trouble understanding what the issue is here.
Any Help is appreciated.
--MyClass.h--
class MyClass{
private:
typedef int (*funcptr)(const int myVar);
funcptr myfuncptr;
int defaultFunc(int myVar);
public:
MyClass(funcptr functionpointer);
MyClass();
void callFunction(int myVar);
};
--MyClass.cpp--
MyClass::MyClass(){
myfuncptr = defaultFunc; //a value of type "int (MyClass::*)(int myVar)" cannot be assigned to an entity of type "MyClass::funcptr"
};
MyClass::MyClass(funcptr functionpointer){
myfuncptr = functionpointer;
};
void MyClass::callFunction(int myVar){
int i = (*myfuncptr)(myVar);
};
int MyClass::defaultFunc(int myVar){
return myVar + 3;
};
Change it into
typedef std::function<int(int)> funcptr;
(btw using is more idiomatic than typedef these days) and
myfuncptr = [this](int x){ return defaultFunc(x); };
I tried what felt like every combination of function pointer typedefs and using but in the end I think that lambda is what worked. Thanks everyone for the help.
--MyClass.h--
class MyClass{
private:
std::function<int(int)> func;
int defaultFunc(int myVar);
public:
MyClass(std::function<bool(int)> func);
MyClass();
void callFunction(int myVar);
};
--MyClass.cpp--
MyClass::MyClass(){
this->func = [=] (int a) {return defaultFunc(a);};
};
MyClass::MyClass(std::function<int(int)> func;){
this->func = func;
};
void MyClass::callFunction(int myVar){
int i = func(myVar);
};
int MyClass::defaultFunc(int myVar){
return myVar + 3;
};
Related
I am using C++ 14 with clang on MacOS Sierra. I want to enforce a rule by design. Following is the rule.
I have a member variable in my class say:
unsigned int m_important_num;
There are 4 methods in my class.
fun1();
fun2();
fun3();
fun4();
Objective:
I want only fun2() to be able to change the value of m_important_num.
Question:
Is it possible to make it compiler error if any method other than fun2() changes the variable?
One possible way is to declare it const somehow empower fun2() to change const variables? Is this a good solution? Or are their any better solutions?
Secondary question:
Is it a wrong design to try do such a thing?
Sort of, with additional layer:
class S1 {
public:
void fun2() { /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
unsigned int m_important_num;
};
class S2 : private S1
{
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
As Yakk commented, if func2 need access to S2 members, CRTP can solve that:
template <typename Derived>
class S1 {
public:
void fun2() { asDerived().foo3(); /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
Derived& asDerived() { return stataic_cast<Derived&>(*this); }
private:
unsigned int m_important_num;
};
class S2 : private S1<S2>
{
// friend class S1<S2>; // If required.
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
Encapsulate it down. Put m_important_num in its own class. Aggregate it in your existing class. Have a getter for it. Then put fun2() as a member function of your inner class.
I little variant (if I understand correctly) of the Jeffrey solution: put the variable in an inner class and make it private; create a public getter and make func2() friend to the inner class.
I mean
struct foo
{
int f1 () { return b0.getVal(); }; // you can read `val` everywhere
void f2 () { b0.val = 42; }; // you can write `val` in f2()
void f3 () { /* b0.val = 42; ERROR ! */ }; // but only in f2()
class bar
{
private:
int val = 24;
public:
int getVal () { return val; }
friend void foo::f2 ();
};
bar b0;
};
In other words: friend is your friend.
If you want to prevent a method from modifying any member in the class you can use the trailing const identifier:
class something{
private:
unsigned int var;
public:
void fun1() const;
void fun2();
void fun3() const;
void fun4() const;
}
Here, only fun2() will be able to modify the variable.
I know there are lots of good answers, but there is also an option that you sort of alluded to in your question:
One possible way is to declare it const somehow empower fun2() to change const variables?
#include <iostream>
using uint = unsigned int;
class Test
{
const uint num;
public:
Test(uint _num)
:
num(_num)
{}
uint get_num() const
{
return num;
}
void can_change_num(uint _new_num)
{
uint& n(const_cast<uint&>(num));
n = _new_num;
}
void cant_change_num(uint _new_num)
{
// num = _new_num; // Doesn't compile
}
};
int main()
{
Test t(1);
std::cout << "Num is " << t.get_num() << "\n";
t.can_change_num(10);
std::cout << "Num is " << t.get_num() << "\n";
return 0;
}
Produces
Num is 1
Num is 10
You already got lots of good answers to your primary question. I'll try to address the secondary one.
Is it a wrong design to try do such a thing?
It's hard to say w/o knowing more about your design. In general anything like this detected during a code review would raise a big red flag. Such a protection makes sense in a case of a big class with convoluted logic/implementation. Otherwise why would you like to go an extra mile and make your code much more complicated? The fact you seek for this can indicate your class became unmanageable.
I'd recommend to consider splitting it to smaller parts with better defined logic where you won't worry such mistakes can happen easily.
i was wondering if is possible make that a method of class points to another method of other class:
consider this:
// Class Foo:
class Foo
{
static int GetA(int a);
static int GetB(int b);
};
int Foo::GetA(int a)
{
return a * 2;
}
int Foo::GetB(int b)
{
return a * 4;
}
// Hooking class methods:
class HookFoo
{
static int HookGetA(int);
static int HookGetB(int);
};
int(HookFoo::*HookGetA)(int) = (int(HookFoo::*)(int))0x0; // (0x0 Memory address) or for example: &Foo::GetA;
int(HookFoo::*HookGetB)(int) = (int(HookFoo::*)(int))0x0; // (0x0 Memory address) or for example: &Foo::GetA;
I know it's possible do some like:
int(*NewHook)(int) = &Foo::GetA;
but how i can do for declare the methods into of a class?
Here is more or less what you tried to achieve (minimal, working example):
class Foo
{
public:
static int GetA(int a);
static int GetB(int b);
};
int Foo::GetA(int a)
{
return a * 2;
}
int Foo::GetB(int b)
{
return b * 4;
}
class HookFoo
{
public:
using FuncType = int(*)(int);
static FuncType HookGetA;
static FuncType HookGetB;
};
// Initialized with Foo::GetA
HookFoo::FuncType HookFoo::HookGetA = &Foo::GetA;
// nullptr'ed
HookFoo::FuncType HookFoo::HookGetB = nullptr;
int main() {
HookFoo::HookGetA(0);
}
For the methods in Foo are static, you can use a simple function pointer type to refer to them. You don't have to use (and can't use actually) a member function pointer in this case.
The using declaration helps to have a more readable code.
When you have correctly initialized your hooks, you can invoke them (thus the pointed functions) as you can see in the main.
I added a couple of visibility specifiers for your methods and data members were all private.
You can use function pointers.
Ex:
class A {
public:
static void say_hello() { cout << "Hello\n"; }
};
class B {
public:
static void(*hook)();
};
void(*B::hook)() = A::say_hello;
int main()
{
B::hook();
}
If you need to hook into functions at a specific address, use a function pointer. You can't reassign functions like that
// typedef your function pointers, it makes the syntax a lot easier
typedef int(*FHook)(int);
class HookFoo
{
static FHook HookGetA;
static FHook HookGetB;
};
// assign to address
FHook HookFoo::HookGetA = (FHook)0x1234;
FHook HookFoo::HookGetB = (FHook)0x5678;
Of course its your job to make sure the addresses are correct.
the explicit function pointer types would be as such:
class HookFoo
{
static int (*HookGetA)(int);
static int (*HookGetB)(int);
};
int (*HookFoo::HookGetA)(int) = (int(*)(int))0x1234;
int (*HookFoo::HookGetB)(int) = (int(*)(int))0x5678;
Value of constant variable can be changed through pointer tricks, but is it possible to do something like this :
class A (){
int x;
public:
void func () const {
//change value of x here
}
}
declare x mutable
class A (){
mutable int x;
public:
void func () const {
//change value of x here
}
};
You have two options:
class C
{
public:
void const_f() const
{
x = 5; // A
auto* p_this = const_cast<C*>(this); // B
p_this->y = 5;
}
private:
mutable int x; // A
int y;
};
A: declare certain members mutable.
B: const_cast to remove constness from the this pointer.
Though this is not appreciated, but C++ provides “Backdoors” which can be used to breach its own regulations, just like dirty pointer tricks. Anyway, you can easily do this by using a casted version of “This” pointer :
class A (){
int x;
public:
void func () const {
//change value of x here
A* ptr = const_cast<A*> (this);
ptr->x= 10; //Voila ! Here you go buddy
}
}
The most important thing to understand here is bitwise/physical/concrete constness and conceptual/meaningwise/logical/abstract constness.
In short:
If the function is conceptually const, make the member data mutable.
Otherwise, make the function non-const.
Just cast 'this', this would be a dirty way to implement your program, do avoid this if you are doing a project or teamwork as others would get confused by this.
class CAST_CLASS (){
int var;
public:
void change_CAST () const {
CAST_CLASS* pointer = const_cast<CAST_CLASS*> (this);
pointer->var= 10;
}};
The other answers don't mention this, but following also modifies "x" (definitely, not advisable):
class A {
int x, &y{x}, *z{&x};
public:
void func () const
{
y = 42; // x is modified now!
*z = 29; // x is modified again!!
}
};
Here is some code:
typedef void (*ACallBack)(int i);
class SomeClass
{
private:
ACallBack aCallBack;
public:
void SetCallBack(ACallBack aCallBack);
};
void SomeClass::SetCallBack(ACallBack aCallBack)
{
this->aCallBack = aCallBack;
}
class SomeOtherClass
{
private:
SomeClass someClass;
public:
void InitializeSomeClass();
private:
void callBackMethod(int i);
};
void SomeOtherClass::InitializeSomeClass()
{
this->changeVariable = 10;
this->someClass.SetCallBack(this->callBackMethod); // DOESN'T WORK
this->someClass.UseCallBack();
}
void SomeOtherClass::callBackMethod(int i)
{
}
void globalCallBack(int i)
{
int myInt = i;
}
int main()
{
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
}
Basically if I try to set my callback function in SomeOtherClass it doesn't work but when I set it globally in main it does. What am I missing here?
Just use std::function and std::bind():
typedef std::function<void(int i)> ACallBack;
// old code pretty much the same
int main()
{
using namespace std::placeholders;
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
SomeOtherClass oC;
sC.SetCallBack(std::bind(&SomeOtherClass::callBackMethod,oC,_1)); //WORKS AS WELL!!
}
In this case you do not really need to pass void *userData but may add it as well if you need old code to compile.
You have to make the method static:
static void callBackMethod(int i, void* userData);
if you need a pointer to a method that is not static, ie an instance method, it becomes more complex.
typedef void ( myclass::*FUNC ) (int i, void* userData);
and if you want to use it, it becomes a hastlle :
myclass obj; // instantiate myclass
FUNC f = &myclass::myfunc; // assign address
( obj.*f ) ( 123, NULL ); // and call it
I need some help on a strange mix between function pointers and templates...
My target :
You have a class : template<typename B> class A, and A instanciate a B member. Now I want to acces B getter/setter.
I tried this :
class B_example
{
public:
B_example(int v):m_var(v){}
int getVar() { return m_var; }
void setVar(int v) { m_var = v; }
private:
int m_var;
};
template<typename B> class A
{
public:
A():m_b(B(5))
{
get = &m_b.getVar;
set = &m_b.setVar;
}
int (B::*get)();
void (B::*set)(int);
private:
B m_b;
};
int main(int argc, char** argv)
{
A<B_example> A_instance;
B_example B_instance(5);
int a = (A_instance.get*)();
std::cout << a << std::endl;
}
Thank's for any help.
Alexandre
First, fix the syntax errors:
get = &B::getVar;
set = &B::setVar;
Then, the member-function pointer needs to be called on an object. Without knowing the purpose of these strange pointers, I can't guess what you want to do here. Maybe you want to call on B_instance:
int a = (B_instance.*A_instance.get)();
Or maybe you want to call it on the m_b object within A_instance; but you can't do that because it's private. If that's the case, you probably just want regular member functions, rather than weird function pointers
int get() {return m_b.getVar();}
void set(int v) {m_b.setVar(v);}
These:
get = &m_b.getVar;
set = &m_b.setVar;
Should be:
get = &B::getVar;
set = &B::setVar;
And (A_instance.get*)() should be (B_instance.*A_instance.get)().