김현우
김현우

Reputation: 23

Return Function Pointer in C++ Class

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

Answers (3)

Jarod42
Jarod42

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');
}

Demo

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

Tom
Tom

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

bartop
bartop

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

Related Questions