C++ - Method/Member 访问

C++ - Method/Member access

我们都知道私有方法和成员只能在 class 内部访问,就像保护方法和成员在 class 和 class 派生的class。但是,它的“访问控制”在哪里? “访问控制”是在编译时发生,还是编译器添加了在运行时控制它的额外机器代码?

我可以像这样创建一个 class 吗:

class Print  
{
        public: 
                void printPublic();

        private:
                void printPrivate();
};

int main() 
{
        Print print;  

        print.printPublic() // Change this to printPrivate() after compiling the code

        return(EXIT_SUCCESS);
}

然后在编译代码后编辑机器代码以调用 printPrivate() 而不是 printPublic() 方法而不会出错?

一旦你摆弄了机器代码,你就不再编译 C++,而是直接用机器代码编程。

因此你的问题有点没有实际意义。

您可以将访问说明符视为本质上的编译时指令,但请注意,编译器可以根据它们做出优化选择。换句话说,它可能是任何一个。 C++ 标准对此也没有任何说明。

«访问控制»发生在编译时

«访问控制»发生在编译时, 用于 C++ 代码。您甚至不需要编辑机器代码——您可以轻松地从汇编语言调用私有方法——所以这表明这仅适用于 C++ 限制。当然,在 运行 时间内没有任何额外的机器代码来控制它——这根本不可能控制谁调用方法。

简单演示。注意函数名称,它是如何损坏的,可能取决于 x86 或 x64 编译器和编译器 - 我的 CL 编译器和 x64 平台的演示 bat 它可以很容易地更改为 x86 或其他编译器

c++代码

class Print  
{
public: 
    void printPublic();

private:
    void printPrivate();
};

// must be not inline or referenced from c++ code or will be droped by compiler!
void Print::printPrivate()// thiscall
{
    DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
void Print::printPublic()// thiscall
{
    DbgPrint("%s<%p>\n", __FUNCTION__, this);
}

extern "C"
{
    // stub impemeted in asm
    void __fastcall Print_printPrivate(Print* This);
    void __fastcall Print_printPublic(Print* This);
};


    Print p;
    //p.printPrivate();//error C2248
    p.printPublic();
    Print_printPrivate(&p);
    Print_printPublic(&p);

和汇编代码(对于ml64

_TEXT segment 'CODE'

extern ?printPrivate@Print@@AEAAXXZ:proc
extern ?printPublic@Print@@QEAAXXZ:proc

Print_printPrivate proc
    jmp ?printPrivate@Print@@AEAAXXZ 
Print_printPrivate endp

Print_printPublic proc
    jmp ?printPublic@Print@@QEAAXXZ 
Print_printPublic endp

_TEXT ENDS
END

还请注意,仅对于 x86,所有 C++ 方法都使用 thiscall 调用约定 - thisECX[ 中的第一个参数 this =42=] 寄存器和堆栈中的下一个 __stdcall - 所以如果方法没有参数(真的是一个 this )我们可以按原样使用 __fastcall 作为 asm 函数,如果存在参数,我们需要将 EDX 压入汇编器存根中。对于 x64 没有这个问题 - 这里只有一个调用约定,但所有这些都与主要问题无关。


带有额外参数的 x86 代码示例,用于显示如何将 __fastcall 转换为 __thiscall

class Print  
{
public: 
    void printPublic(int a, int b)// thiscall
    {
        DbgPrint("%s<%p>(%x, %x)\n", __FUNCTION__, this, a, b);
    }

private:
    void printPrivate(int a, int b);
};

// must be not inline or referenced from c++ code or will be droped by compiler!
void Print::printPrivate(int a, int b)// thiscall
{
    DbgPrint("%s<%p>(%x, %x)\n", __FUNCTION__, this, a, b);
}

extern "C"
{
    // stub impemeted in asm
    void __fastcall Print_printPrivate(Print* This, int a, int b);
    void __fastcall Print_printPublic(Print* This, int a, int b);
};
        Print p;
        //p.printPrivate(1,2);//error C2248
        p.printPublic(1, 2);
        Print_printPrivate(&p, 1, 2);
        Print_printPublic(&p, 1, 2);

和asm

.686p

_TEXT segment

extern ?printPublic@Print@@QAEXHH@Z:proc
extern ?printPrivate@Print@@AAEXHH@Z:proc

@Print_printPrivate@12 proc
    xchg [esp],edx
    push edx
    jmp ?printPrivate@Print@@AAEXHH@Z 
@Print_printPrivate@12 endp

@Print_printPublic@12 proc
    xchg [esp],edx
    push edx
    jmp ?printPublic@Print@@QAEXHH@Z
@Print_printPublic@12 endp

_TEXT ends

end