代码之家  ›  专栏  ›  技术社区  ›  Potatoswatter

清除C++访问资格最干净的方法是什么?

  •  2
  • Potatoswatter  · 技术社区  · 15 年前

    但是,如前所述,这会导致每个翻译单元复制一些小对象和访问器函数,从而导致令人讨厌的级联。有没有一个规范的方法来做到这一点,比如说推进最佳实践?

    抱歉的坏幽默,但这不是无缘无故的,我们不会希望这个代码是“安全的工作”!

    /* This hack installs a static initializer, so to avoid the ordering fiasco,
    make one fresh copy per translation unit, via anonymous namespace. */
    namespace {
    
    template< typename T, T value, T &dest >
    struct class_rape {
        class_rape() { dest = value; } // you've been raped in the class!
        static class_rape r;
    };
    template< typename T, T value, T &dest >
    class_rape< T, value, dest > class_rape< T, value, dest >::r;
    
    
    // Usage (cvt_[w]filebuf is a specialization of GCC basic_filebuf)
    
    typedef bool cvt_filebuf::*cvt_fb_reading_t;
    typedef bool cvt_wfilebuf::*cvt_wfb_reading_t;
    
    /* Access these variables, or functions accessing them (applies recursively),
    only in anonymous namespace or in non-header file, per one-definition rule. */
    cvt_fb_reading_t cvt_filebuf_reading;
    cvt_wfb_reading_t cvt_wfilebuf_reading;
    
    template struct class_rape
        < cvt_fb_reading_t, &cvt_filebuf::_M_reading, cvt_filebuf_reading >;
    template struct class_rape
        < cvt_wfb_reading_t, &cvt_wfilebuf::_M_reading, cvt_wfilebuf_reading >;
    
    }
    

    http://pastie.org/1188625 .

    更新

    我在下面的回答中解决了重复问题。因此,现在我对一个确定性的、定义良好的解决方案感兴趣,它不涉及编辑任何目标代码,并且允许同时对模板的多个专门化进行黑客攻击。(给定的hack需要为每个目标模板专门化提供一个新的实例化。)

    3 回复  |  直到 11 年前
        1
  •  3
  •   sbi    15 年前

    非法访问:

    class ClassIWantToViolate
    {
        // Internal State
        public:
            template<typename T> void violate() {} // Do nothing
    };
    

    namespace { struct Attack {}; }
    
    template<>
    void ClassIWantToViolate::violate<Attack>()
    {
         // Access to internal state here.
    
         // This is your own version of violate based on a local specialization
         // Thus it is unique but still has access to internal state of the class.
    }
    
        2
  •  0
  •   dgnorton    15 年前

    我可能会选择不那么聪明的方法。从外部访问类的私有成员是一件非常罕见的事情,至少对我来说是这样(从来没有这样做过)。在我的实现中,我能在几分钟内完成这个。。。

    • 删除的所有实例 来自邪恶的流.h

    然后此代码编译:

    #include <fstream>
    #include "evil_fstream.h"
    
    using namespace std;
    
    typedef evil::basic_filebuf<char, char_traits<char> > evil_filebuf_t;
    
    int main() {
    
       std::basic_filebuf<char, char_traits<char> > fb;
    
       evil_filebuf_t* efb = (evil_filebuf_t*)&fb;
    
       efb->_Pcvt; // access a private member
    
       return 1;
    }
    
        3
  •  0
  •   Potatoswatter    15 年前

    我可以避免静态初始化顺序失败和重复问题,通过使变量真正全局化,而仅仅是

    typedef bool cvt_filebuf::*cvt_fb_reading_t;
    typedef bool cvt_wfilebuf::*cvt_wfb_reading_t;
    
    /* Place accessible variables in global, non-anonymous namespace. */
    cvt_fb_reading_t cvt_filebuf_reading;
    cvt_wfb_reading_t cvt_wfilebuf_reading;
    
    /* This hack installs a static initializer, so to avoid the ordering fiasco,
    make one fresh copy per translation unit, via anonymous namespace. */
    namespace {
    
    template< typename T, T value, T &dest >
    class class_rape { // change access qualification of hack to guarantee ODR, LOL
        class_rape() { dest = value; } // you've been raped in the class!
        static class_rape r;
    };
    template< typename T, T value, T &dest >
    class_rape< T, value, dest > class_rape< T, value, dest >::r;
    
    template struct class_rape
        < cvt_fb_reading_t, &cvt_filebuf::_M_reading, cvt_filebuf_reading >;
    template struct class_rape
        < cvt_wfb_reading_t, &cvt_wfilebuf::_M_reading, cvt_wfilebuf_reading >;
    
    }
    
    /* Accessor functions go here, also outside anonymous namespace. */