Reputation: 23
This is the c ++ source I wrote. What I want to do is run init(), a member function of class A, and get_func returns the address of a function in a(), b(), c(), d(). Finally, func () is executed and I hope to see b. It seems very simple, but now this problem is bothering me.
The compiler gives me the following error: - 'choice' was not declared in this scope - 'a' was not declared in this scope return a (); - no matching function for call to 'A :: init (char)' a.init ('b');
What am i missing?
#include <iostream>
class A {
private:
int (A::*get_func())();
int a(){printf("a");}
int b(){printf("b");}
int c(){printf("c");}
int d(){printf("d");}
public:
A();
~A();
int init();
char choice;
}
A::init(char ch) {
this->choice = ch;
int (A::*func)() = get_func();
func();
}
int (A::*get_func())() {
switch(choice) {
case 'a' :
return a;
case 'b' :
return b;
case 'c' :
return c;
case 'd' :
return d;
}
}
int main() {
A a;
a.init('b');
}
Upvotes: 0
Views: 659
Reputation: 218323
You have several mistakes in your code, following compile:
#include <iostream>
class A {
private:
int (A::*get_func())();
int a() {printf("a"); return 0;}
int b() {printf("b"); return 0;}
int c() {printf("c"); return 0;}
int d() {printf("d"); return 0;}
public:
A() = default;
~A() = default;
void init(char);
char choice;
};
void A::init(char ch) {
this->choice = ch;
int (A::*func)() = get_func();
(this->*func)(); // ->* or .* is use to call member function
}
int (A::*A::get_func())() // You forget one `A::`, so define a free function.
{
switch(choice) {
case 'a' :
return &A::a; // &A:: is require for pointer on member
// due to compatibility with C
// & is not required for address of free function :/
case 'b' :
return &A::b;
case 'c' :
return &A::c;
case 'd' :
return &A::d;
}
return nullptr;
}
int main() {
A a;
a.init('b');
}
To avoid strange and ugly syntax, I suggest using typedef or trailling return type
auto get_func() -> int (A::*)();
and in out of class definition
auto A::get_func() -> int (A::*)();
Upvotes: 1
Reputation: 929
If you would like to try the inheritance-based approach:
class A {
public:
A();
~A();
virtual int init(){ printf("a"); }
};
class B : public A {
public:
B();
~B();
int init(){ printf("b"); }
};
class C : public A {
public:
C();
~C();
int init(){ printf("c"); }
};
class D : public A {
public:
D();
~D();
int init(){ printf("d"); }
};
If you would like the base class (A) to be abstract:
class A {
public:
A();
~A();
virtual int init() = 0;
};
Upvotes: 0
Reputation: 10315
This should do the trick:
class A {
private:
int a(){printf("a");}
int b(){printf("b");}
int c(){printf("c");}
int d(){printf("d");}
public:
using func = int (A::*)();
A();
~A();
char choice;
private:
func foo();
};
A::func A::foo() {
switch(choice) {
case 'a' :
return &A::a;
case 'b' :
return &A::b;
case 'c' :
return &A::c;
case 'd' :
return &A::d;
}
}
Instead of returning function pointer You were calling these functions instead. Secondly, I would suggest using typedefs/using with member function types. Notice that You did not add semicolon at the end of class definition.
Upvotes: 2