Objective C ++, 3rd edition, item 15: provides raw resources (raw resources) in resource-management classes (resource management class)

Source: Internet
Author: User

Item 15: provide raw resources access in resource-management classes (resource management class)

By Scott Meyers

Translator: fatalerror99 (itepub's nirvana)

Release: http://blog.csdn.net/fatalerror99/

Resource-managing classes (resource management class) is really great. They are the bastion of your defense against resource leaks. Without such a leak is the basic feature of a well-designed system. In a perfect world, you can rely on such classes in all your interactions with resources. You never need to tarnish your hands with direct access to raw resources. However, this world is not perfect. Many APIs are directly related to resources, so unless you plan to give up using such an APIS (rarely a reality, you have to bypass resource-management object (resource management object) and process raw resources directly ).

For example, item 13 describes how to use smart pointers (smart pointers) Like auto_ptr or tr1: shared_ptr to hold factory functions (factory functions) Like createinvestment) the call result idea:

STD: tr1: shared_ptr <investment>Pinv (createinvestment (); // from item 13

Assume that the function you intend to use works with the investment objects function as follows:

Int daysheld (const investment * PI); // return number of days
// Investment has been held

You want to call it like this,

Int days = daysheld (pinv); // error!

But this Code cannot be compiled: daysheld requires a bare investment * pointer, But you pass it an object of the type tr1: shared_ptr <investment>.

You need to convert an object of raiI class (tr1: shared_ptr in the current situation) to the raw resource contained in it (raw Resource) (for example, underlying investment *). There are two common methods: explicit conversion and implicit conversion ).

Tr1: Both shared_ptr and auto_ptr provide a get member function (member function) to implement an explicit it conversion (display conversion), that is, to return a smart pointer object (smart pointer object) internal raw pointer (raw pointer) (a copy ):

Int days = daysheld (pinv.Get ()); // Fine, passes the raw pointer
// In pinv to daysheld

Just like all smart pointer classes, tr1: shared_ptr and auto_ptr both reload pointer dereferencing operators) (operator-> and operator *), which allows implicit conversion (implicit conversion) to the underlying raw pointers (bare pointer ):

Class investment {// root class for a hierarchy
Public: // of investors types
Bool istaxfree () const;
...
};

Investment * createinvestment (); // factory function

STD: tr1: shared_ptr <investment> // have tr1: shared_ptr
PI1 (createinvestment (); // manage a resource

Bool taxable1 =! (PI1-> istaxfree (); // access resource
// Via operator->
...
STD: auto_ptr <investment> Pi2 (createinvestment (); // have auto_ptr
// Manage
// Resource

Bool taxable2 =! ((*PI2). istaxfree (); // access resource
// Via operator *

...

In some cases, it is necessary to obtain raw resources (raw resources) in the raiI object. Therefore, some raiI class designers can smooth the brakes by providing an implicit conversion function (implicit conversion function. For example, consider the following raiI class, which provides the original fonts (font) for 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
{} // C api does

~ Font () {releasefont (f);} // release resource

PRIVATE:
Fonthandle F; // The raw Font Resource
};

Suppose there is a huge font-related (font-related) c api that can only deal with fonthandle, which frequently needs to convert font objects to fonthandles. Font class may provide an explicit it conversion function like get (display Conversion Function ):

Class font {
Public:
...
Fonthandle get () const {return F ;}// Explicit Conversion Function
...
};

Unfortunately, this requires customers to call get every time they want to deal with this 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 may find that the need for explicit requests for this conversion is depressing enough to avoid using this class. In turn, this increases the leaking fonts (font leakage) opportunity, and every thing is avoided by designing font classes.

You can choose to provide an implicit conversion function (implicit conversion function) to Font ):

Class font {
Public:
...
Operator fonthandle () const {return F ;}// Implicit conversion function
...
};

In this way, the call to c api is simple and natural:

Font F (getfont ());
Int newfontsize;
...

Changefontsize (F, Newfontsize); // implicitly convert font
// To fonthandle

The disadvantage is that implicit conversions (implicit conversion) increases the chance of errors. For example, a customer may accidentally create a fonthandle where they want to use the font:

Font F1 (getfont ());

...

FonthandleF2 = 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 managed by font object F1, but this fonthandle can also be used directly by using F2. This is almost no good thing. For example, if F1 is destroyed, the font is released, and F2 is suspended by dangle ).

Whether or not Explicit conversions are provided from a raiI class to its underlying resources (for example, using a get member function (member function )) or whether implicit conversion (implicit conversion) is allowed depends on the specific task that the raiI class is designed to perform and the situation in which it is planned to be used. The best design is probably the one that sticks to item 18's recommendations (making interfaces (interfaces) Easy to use correctly, and making it difficult to use incorrectly. Generally, an explicit conversion function similar to get is more desirable because it minimizes the chance of unexpected type conversions. However, sometimes the increased naturalness through implicit type conversions (implicit type conversion) will cause the balance to tilt in that direction.

You may have realized that the function returns a raw Resource (raw Resource) inside the raiI class against encapsulation (encapsulation ). This is correct, but it is not as designed as it seems at first. RaiI classes does not exist to encapsulate anything. It exists to ensure the occurrence of a specific action, resource release. If you want to improve the resource's encapsulation (encapsulation) status above this main function, this is not necessary. In addition, some raiI classes combine strict encapsulation and very loose encapsulation of underlying resources. For example, tr1: shared_ptr encapsulates its reference-counting machinery (reference counting mechanism), but it still provides simple access to its raw pointer (bare pointer. Like most well-designed classes, it hides things that customers don't need to see, but it also makes them accessible.

Things to remember

  • APIS often needs to access raw resources. Therefore, every raiI class should provide a way to obtain the resources it manages.
  • Access can be performed through explicit or implicit conversion. Generally, Explicit conversions are more secure, while implicit conversion (implicit conversion) is more convenient for customers.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.