c++ – A pointer to a class method

Question:

It is required to make a pointer to a method. In this case, there are a number of methods with the same declaration. Here they are all in public .

The method pointer is called Metric .

The compiler swears at the marked line. Message:

error: cannot convert 'std :: vector (CTesting ::) ()' to 'std :: vector ( ) ()' in assignment this-> Metric = & this-> ExTimeofWork;

Apparently there is something with the namespace. I tried to specify it explicitly at the place of the method call. Does not work. If such a construction is done outside the class, then everything is fine.

Explain, please, through what mechanisms this error occurs? How do I fix it?

class CTesting
{
    private:
        // code     
        vector<double> ( *Metric)();

    public:


        vector<double> ExTimeofWork();
        vector<double> ExTimeGenerationToAccept();
        vector<double> ExTimePoolToAccept();
        vector<double> ExMaxTimeGenerationToAccept();
        vector<double> ExMaxTimePoolToAccept();

        vector<double> GetTimeGenerationToAccept();
        vector<double> GetTimePoolToAccept();
        vector<double> GetTimeofWork();
};

void CTesting::Execute()
{
    this->Metric = &this->ExTimeofWork; //Ошибка!!!!!!!!!!!!!!!!!!!!
    //... Code

    //...
    return;
}

Answer:

You are confusing a function pointer and a member function pointer, they are different things .

Try to define Metric like this:

vector<double> (CTesting::*Metric)();

Accordingly, the assignment should look like

this->Metric = &CTesting::ExTimeofWork;

and the call is

(this->*Metric)();

Yes, this is a weird syntax, it can't be helped.


The idea that @igumnov described in the comments is this. You don't need to combine all possible behaviors in the CTesting class. Do not union of all possible metrics, but split into cases and use composition.

abstract class CTesting
{
    CTestingData* data;

public:
    virtual vector<double> Metric() = 0;
};

class CExTimeofworkTesting : public CTesting
{
public:
    vector<double> Metric() override
    {
        // тут содержимое ExTimeofWork()
    }
};

class CExTimeGenerationToAcceptTesting : public CTesting
{
public:
    vector<double> Metric() override
    {
        // тут содержимое ExTimeGenerationToAccept()
    }
};

Don't forget to separate the shared data into the CTestingData class. Now your code will simply be like this:

vector<CTesting*> testings =
{
    new CExTimeofworkTesting(data),
    new CExMaxTimePoolToAcceptTesting(data)
    // ...
};

for (auto t : testings)
    t->Metric();

This way you have simple classes, fewer extensibility problems, separation of concerns, and a simple virtual function. Profit!

Scroll to Top