C++中的成员函数是如何实现的?

How member functions are implemented in C++?

我在某处读到,成员函数就像 C++ 中的普通函数,但有一个额外的隐式 this 参数。

所以我认为这个程序无法区分两个func。但是程序运行成功了。那么上面的说法是不是错了呢?

#include <iostream>

class MyCls {
    public:
    void func(int i) {
        std::cout << "Member" << i << std::endl;
    }
};

void func(MyCls m, int i) {
    std::cout << "Outside" << i << std::endl;
}

int main() {
    MyCls m;
    // Thought both would have same signature void func(MyCls, int). But program compiled.
    m.func(4);
    func(m, 5);
    return 0;

查看 this site,如果你 google 完全相同的问题,只是为了从其他教程中挑选一个,你会发现这个

Member functions are the functions, which have their declaration inside the class definition and works on the data members of the class. The definition of member functions can be inside or outside the definition of class.

If the member function is defined inside the class definition it can be defined directly, but if its defined outside the class, then we have to use the scope resolution :: operator along with class name alng with function name.

如您所见,成员函数是属于 class 实例的函数,可以访问对象的成员和指向自身对象的指针 this

当然,在您的示例中,您正在访问

m.func(4)

这是在写

时在classMyCls的对象实例中定义的成员函数
func(m, 5);

您正在将 class MyCls 的对象实例传递给全局范围内的函数(按值,如果它是您想要的行为方式,您也应该研究这一点)而无需使用它,只是为了验证你的想法的连贯性。

我建议您从一个很好的 C++ 教程开始学习该语言的 OOP 范例。

函数有不同的签名,可以在生成的目标文件列表符号中看到:

$ g++ -c my.cpp -o my.o
$ nm -s my.o

                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
00000000000000c7 t _GLOBAL__sub_I__Z4func5MyClsi
0000000000000046 T main
000000000000007e t _Z41__static_initialization_and_destruction_0ii
0000000000000000 T _Z4func5MyClsi
0000000000000000 W _ZN5MyCls4funcEi
                 U _ZNSolsEi
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 r _ZStL19piecewise_construct
0000000000000000 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

所以回答你的问题,你的第二个假设是错误的:当然,编译器总是可以通过类似于命名空间的机制(我猜)区分普通函数和 class 成员。