zoukankan      html  css  js  c++  java
  • Effective C++ 笔记 —— Item 15: Provide access to raw resources in resourcemanaging classes.

    ,Item 13 introduces the idea of using smart pointers like auto_ptr or tr1::shared_ptr to hold the result of a call to a factory function like createInvestment:

    std::tr1::shared_ptr<Investment> pInv(createInvestment()); // from Item 13

    Suppose that a function you’d like to use when working with Investment objects is this:

    int daysHeld(const Investment *pi); // return number of days investment has been held 

    You’d like to call it like this,:

    int days = daysHeld(pInv); // error!

    tr1::shared_ptr and auto_ptr both offer a get member function to perform an explicit conversion, i.e., to return (a copy of) the raw pointer inside the smart pointer object:

    int days = daysHeld(pInv.get()); // fine, passes the raw pointer in pInv to daysHeld

    Like virtually all smart pointer classes, tr1::shared_ptr and auto_ptr also overload the pointer dereferencing operators (operator-> and operator*), and this allows implicit conversion to the underlying raw pointers:

    class Investment 
    { // root class for a hierarchy of investment types
    public:
        bool isTaxFree() const;
        //...
    };
    
    Investment* createInvestment(); // factory function have tr1::shared_ptr manage a resource
    std::tr1::shared_ptr<Investment> pi1(createInvestment());
    
    bool taxable1 = !(pi1->isTaxFree()); // access resource via operator-> 
    std::auto_ptr<Investment> pi2(createInvestment()); // have auto_ptr
    
    // manage a resource via operator*
    bool taxable2 = !((*pi2).isTaxFree()); // access resource
    // ...

    Consider this RAII class for fonts that are native to a C API:

    FontHandle getFont(); // from C API — params omitted for simplicity
    
    void releaseFont(FontHandle fh); // from the same C API
    
    class Font 
    { // RAII class
    public:
        explicit Font(FontHandle fh) // acquire resource;
            : f(fh) // use pass-by-value, because the C API does
        {} 
        ~Font() { releaseFont(f); } // release resource
        //... // handle copying (see Item 14)
    private:
        FontHandle f; // the raw font resource
    };

    Assuming there’s a large font-related C API that deals entirely with FontHandles, there will be a frequent need to convert from Font objects to FontHandles. The Font class could offer an explicit conversion function such as get:

    class Font {
    public:
        //...
        FontHandle get() const { return f; } // explicit conversion function
        //...
    };

    Unfortunately, this would require that clients call get every time they want to communicate with the API:

    void changeFontSize(FontHandle f, int newSize); // from the C API
    Font f(getFont());
    int newFontSize;
    //...
    changeFontSize(f.get(), newFontSize); // explicitly convert Font to FontHandle

    Some programmers might find the need to explicitly request such conversions off-putting enough to avoid using the class. That, in turn, would increase the chances of leaking fonts, the very thing the Font class is designed to prevent. The alternative is to have Font offer an implicit conversion function to its FontHandle:

    class Font 
    {
    public: //... operator FontHandle() const // implicit conversion function { return f; } //... };

    That makes calling into the C API easy and natural:

    Font f(getFont());
    int newFontSize;
    //...
    changeFontSize(f, newFontSize); // implicitly convert Font to FontHandle

    The downside is that implicit conversions increase the chance of errors. For example, a client might accidently create a FontHandle when a Font was intended:

    Font f1(getFont());
    //...
    FontHandle f2 = f1; // oops! meant to copy a Font object, but instead implicitly converted f1 into its underlying FontHandle, then copied that

    Now the program has a FontHandle being managed by the Font object f1, but the FontHandle is also available for direct use as f2. That’s almost never good. For example, when f1 is destroyed, the font will be released, and f2 will dangle.

    Things to Remember:

    • APIs often require access to raw resources, so each RAII class should offer a way to get at the resource it manages.
    • Access may be via explicit conversion or implicit conversion. In general, explicit conversion is safer, but implicit conversion is more convenient for clients.
  • 相关阅读:
    SqlServer2008 / SqlServer2012 禁用windows登录,sa忘记密码或密码过期如何登陆
    windows下批处理保留指定日期下的文件
    centos7上使用git clone出现问题
    VS2015编译Teamtalk的Windows客户端(转)
    Mac Book触摸板失灵的解决办法(触摸板按下失灵)
    系统设计原则
    命令“regsvr32 /s /n /i:user "XXXXXX"”已退出,代码为 3
    Android实现开机自动运行程序
    Java并发之CyclicBarrier、CountDownLatch、Phaser
    Java多线程之ThreadLocal
  • 原文地址:https://www.cnblogs.com/zoneofmine/p/15220432.html
Copyright © 2011-2022 走看看