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.
  • 相关阅读:
    首先,编写一个类ChongZai,该类中有3个重载的方法void print();其次, 再编写一个主类来测试ChongZai类的功能。
    创建一个Point类,有成员变量x,y,方法getX(),setX(),还有一个构造方 法初始化x和y。创建类主类A来测试它。
    机动车
    people 0919
    创建一个三角形类,成员变量三边,方法求周长,创建类主类A来测试它。
    百鸡百钱修改
    java 面向对象--------时间作业
    序列化、反序列化
    通讯录
    Java正则表达式
  • 原文地址:https://www.cnblogs.com/zoneofmine/p/15220432.html
Copyright © 2011-2022 走看看