dcsimg
Login | Register   
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


advertisement
 

Preserve Code Safety with Conversion Operators-3 : Page 3


advertisement

WEBINAR:

On-Demand

Application Security Testing: An Integral Part of DevOps


Declaring Constructors 'explicit'
To correct this flaw, first declare the constructor explicit:

class USD { public: explicit USD(__int64 d=0, int c=0): dollars(d), cents(c){} ...

This way, only assignments of USD objects will be accepted:

payment=USD(payment*1.05); //fine payment=payment*1.05; //compilation error

Adding another Constructor
The second fix is to add another constructor that takes an argument of type double:


class USD { public: explicit USD(double val) { dollars=val; //copy the integral part long double temp=(val-dollars)*100; //extract cents //avoid truncation e.g., .6699 to 66 rather than 67 cents=temp+0.5; } };

Here again, the constructor is declared 'explicit' to avoid inadvertent assignments. To increase payment by 5 percent, use the following form instead:

payment=USD(payment*1.05);

Now, everything's in order. Inadvertent conversions by a promiscuous constructor are blocked, whereas well-behaved conversions to double that rely on the conversion operator are permitted.

Better Safe than Sorry
Programmers often moan about the lack of a const char * conversion operator in class std::string. If std::string had such an operator, you could write

string filename; ifstream inf(filename);

Instead of the ugly:

ifstream inf(filename.c_str());

However, the C++ standardization committee decided not to include a conversion operator of this kind in std::string because it might cause nasty bugs in certain libraries in which char * are used extensively. In this case, the committee adhered to the "better safe than sorry" idiom. By contrast, <fstream> objects contain a conversion operator to type void* which enables you to use them like this:

ifstream inf("myfile"); if (inf) //using void * conversion operator //use the file else //failure

When you design your own classes, consider which automatic conversions are desirable and which ones should be disabled. Then, enable legitimate conversions by defining the appropriate conversion operators while blocking undesirable conversions by declaring constructors explicit.


Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
×
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.
Thanks for your registration, follow us on our social networks to keep up-to-date