How the function of the class itself has a different address from its objects' functions' addresses?

132 Views Asked by At

I know in classes that each object's variables will have a different address in memory. However, member functions' addresses are common between objects, so only one function is loaded in memory with a common address.

The issue is I was trying to print the address of a certain member function of the class itself and I expected it to be the same as the member function's address of all objects. But I found that it's different from them!! That was very strange for me.

#include<iostream>
using namespace std;
    
class LuckyNum {
    public:
        void PrintAddress() {
            printf("\tFunction address :%p\n", &LuckyNum::PrintAddress);
        }
};
    
int main() {
    LuckyNum r1;
    cout << "r1:\n";
    r1.PrintAddress();

    LuckyNum r2;
    cout << "r2:\n";
    r2.PrintAddress();

    cout << "LuckyNum Class:\n";
    printf("\tFunction address :%p\n", &LuckyNum::PrintAddress);

    return 0;
}

/*Output!! :
r1:
    Function address :0000007acdbffda0
r2:
    Function address :0000007acdbffda0
LuckyNum Class:
    Function address :0000007acdbffde0 => HOW!! it should equal the above two addresses, shouldn't it?
*/
1

There are 1 best solutions below

0
chrysante On

The function call

printf("\tFunction address :%p\n", &LuckyNum::PrintAddress);

invokes undefined behaviour. printf is not typesafe, and &LuckyNum::PrintAddress is not a pointer. It is a pointer to member, which is a very different thing and it's representation is implementation defined. See the following program:

#include <iostream>
#include <vector>
#include <cstring>

class LuckyNum {
public:
    std::vector<char> getAddress() {
        auto const address = &LuckyNum::getAddress;
        std::vector<char> result(sizeof(address));
        std::memcpy(result.data(), &address, sizeof(address));
        return result;
    }
};
 
int main() {
    LuckyNum r;
    auto address = r.getAddress();
 
    auto const address2 = &LuckyNum::getAddress;
    if (address.size() != sizeof(address2)) {
        std::cout << "Fail\n";
        return -1;
    }
    int result = std::memcmp(address.data(), &address2, address.size());
    if (result != 0) {
        std::cout << "Fail\n";
        return -1;
    }
    std::cout << "Success\n";
    return 0;
}

The getAddress() function stores the pointer to member &LuckyNum::getAddress in a vector of bytes and returns it. main then obtains one pointer to member via the getAddress() function and another one directly via &LuckyNum::getAddress. Then it compares to the byte by byte and if you run the program (with gcc at least) you will find that the two pointers to member are indeed equal.