【问题标题】:C++ - Method/Member accessC++ - 方法/成员访问
【发布时间】:2017-08-24 08:36:56
【问题描述】:

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

我可以创建这样的类吗:

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() 方法没有错误?

【问题讨论】:

  • 所以你问的是访问控制是内置在二进制文件中还是纯粹是在编译时检查的东西?
  • 赞成这个问题写得很好,如果有点奇怪。
  • @NathanOliver:正确。

标签: c++ compilation private public


【解决方案1】:

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

因此,您的问题有些实际意义。

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

【讨论】:

    【解决方案2】:

    «访问控制»发生在编译时,用于 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);
    

    和asm代码(对于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 调用约定 - ECX 寄存器中的第一个参数 this 和堆栈中的下一个参数__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
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2011-11-21
        • 2010-10-27
        • 1970-01-01
        • 2014-07-29
        • 2016-05-18
        • 1970-01-01
        • 1970-01-01
        • 2012-01-13
        • 2014-01-25
        相关资源
        最近更新 更多