1

There is an objects with field double (A :: *ptrToFunc)(); Object B has got A; Can't use it in objects B.

class Foo
{
public:
    
    double (Foo :: *ptrToFunc)();
    
private:
    double func1();
    double func2();
    
public:
    Foo() : ptrToFunc{ &Foo::func1 } {}
}

class B
{
public:
    Foo obj();
    double countVal()
    {
        return (obj.*ptrToFunc)();  // use of undeclared identifier ptrToFunc
        return (obj.ptrToFunc)();  // called object (..) not a function or function pointer
    }
}

int main()
{
    B obj_B;
    double var = obj_B.countVal();
    return 0;
}

I have read C++ Tutorial: Pointer-to-Member Function but it doesn't help me.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    please review your code formatting. And please ask a quesiton. And please explain what "I cant" means. WHen your code has errors, include the compiler error message in the quesiton – 463035818_is_not_an_ai Dec 15 '22 at 13:04
  • `Foo obj()` is vexing parse. It declares a `obj` as a member function. – Jason Dec 15 '22 at 13:08
  • you want to get the pointer `obj.ptrToFunc` (that's where the pointer is stored) and then use that pointer on `obj` again? Hint: you'd write `obj` twice – user253751 Dec 15 '22 at 13:09
  • `Foo obj();` is declaring a method named `obj` that has no parameters and returns `Foo`. I doubt this is what you meant. – wohlstad Dec 15 '22 at 13:10

2 Answers2

4

There are 2 problems with your code.

Problem 1

Foo obj(); is a member function declaration and not a data member declaration because of vexing parse (note the absence of "most"). That is, Foo obj(); declares a member function named obj with no parameter and return type Foo.

To solve this, replace it with:

//-----vv--->use braces
Foo obj{};

Problem 2

The second problem is that the syntax return (obj.*ptrToFunc)(); is incorrect as obj.ptrToFunc refers to the pointer and we still need to use that pointer on an object (as shown below).

To solve this 2nd problem, replace it with:

(obj.*(obj.ptrToFunc))() // or same as (obj.*obj.ptrToFunc)() 

Working demo


With , you can make the code more readable by using std::invoke:

double countVal()
{
//--------------vvvvvv--------------------->use invoke
    return std::invoke(obj.ptrToFunc, obj); 
}

Demo c++17

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Jason
  • 36,170
  • 5
  • 26
  • 60
  • `obj.*obj.ptrToFunc` looks pretty weird. I'd add more parens: `obj.*(obj.ptrToFunc)` – user253751 Dec 15 '22 at 13:14
  • about Foo obj(); my bad; i didn't mean obj is a method, don't copy/paste my classes because there are quite big, i was trying to write a small example – Vadim Shestak Dec 15 '22 at 13:19
  • @VadimShestak It's ok, also refer to [most vexing parse](https://stackoverflow.com/questions/38951362/most-vexing-parse). – Jason Dec 15 '22 at 13:20
  • To make the (not very frequently used, in the wild) invocation a little gentler on the eyes: `auto func{ obj.ptrToFunc }; return (obj.*func)();` – Eljay Dec 15 '22 at 13:39
  • @Eljay Yeah, `auto` can be used here to make the code more readable(?). – Jason Dec 15 '22 at 13:45
  • On modern C++ the problem 2 can be solved in a quite readable way by using `std::invoke(obj.Foo::ptrToFunc, obj)` – kriss Dec 15 '22 at 14:12
0

Another slightly different way to solve the issues pointed out by the accepted answer. I rather like std::invoke from 'functional' than can call whatever is callable without too much trouble.

Also made the code self contained to make it easy to try it for future readers.

#include <iostream>
#include <functional> class Foo { public:
    
    double (Foo::*ptrToFunc)();
     private:
    double func1() { return 1.0;}
    double func2() { return 2.0;}
     public:
    Foo() : ptrToFunc{&Foo::func2} {} };

class B { public:
    Foo obj = Foo();
    double countVal()
    {
        return std::invoke(obj.Foo::ptrToFunc, obj);       
    } };

int main() {
    B obj_B;
    double var = obj_B.countVal();
    std::cout << var << std::endl;
    return 0; }
kriss
  • 23,497
  • 17
  • 97
  • 116