Search code examples
c++function-pointersprivate-members

Function Pointers and Access - Why is this code legal?


I came across something which surprised me quite recently and it'd be nice to have some clarification on it.

Say I have a class A which is comprised of the following:

#include "B.h"

class A {

private:
    B* inst_b;
    std::mt19937 mt_eng; 

    static void update_routine(double& _p, std::mt19937& _eng) {
        // does stuff, not important here
    }

public:
    A() {
        std::random_device rd;
        mt_eng = std::mt19937(rd());
    }

    void updateP() {
        inst_b->update_quantity(update_routine, mt_eng);
    }

    //...
};

and a class B which is as follows:

#include <random>

class B {

protected:
    double qty; 
    //...
public:
    B() {
        qty = 0.0;
    }

    void update_quantity(void(*fptr)(double&, std::mt19937&), std::mt19937& _eng) {
        fptr(qty, _eng); // no error here
    }

    //...
};

Now I would've thought that the compiler would complain about trying to call the function in the body of update_quantity as update_routine of A is a private member function and therefore I'd think trying to call it from B would result in an inaccessible method error or something along those lines - even if it has been passed as a function pointer.

In my project when I do the above it compiles and executes successfully - why is this? Granted, it's quite useful for me that it indeed does compile and run but I'd like to understand why this is the case.

P.S: I apologise if this is a duplicate, please link the relevant topic if this is the case.


Solution

  • class B {
    
    protected:
        double qty; 
    public:
        B() {
            qty = 0.0;
        }
    
        void update_quantity(void(*fptr)(double&, std::mt19937&), std::mt19937& _eng) {
            fptr(qty, _eng); // no error here
        }
    
    };
    

    There is no reference in the above code to the A class. You are de-referencing the fptr in the update_quantityfunction, but the prototype for fptr doesn't have any references to the A class-so there is no privilege violation from class B to A.

    The address of update_routine might be passed in as a function pointer parameter- but the A function is still not directly encoded in the class of B, as written. In other words, if the function pointer is a parameter only, then de-referencing this function pointer parameter does not necessarily cause a class privilege violation.

    fptr is strictly local to update_quantity and is not considered part of the A class..