0

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');
}
10
  • What is get_func supposed to return? What happens with e.g. return a();? What is really returned? Commented Jul 23, 2018 at 8:00
  • 1
    return a(); will call a() and the value returned from a is returned. Commented Jul 23, 2018 at 8:03
  • 3
    There are a large number of mistakes in this code, it would be better to start simpler, check it compiles, and then gradually add new things Commented Jul 23, 2018 at 8:07
  • 1
    I don't like to ask this kind of question, but have you considered using inheritance instead of this kind of architecture? Commented Jul 23, 2018 at 8:09
  • 1
    With C++11 I would recommend returning a lambda expression so return some std::function type. Commented Jul 23, 2018 at 8:17

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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::*)();

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.