C++显式构造函数 [翻译]
Posted 0x16
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++显式构造函数 [翻译]相关的知识,希望对你有一定的参考价值。
原文地址:http://www.codeproject.com/KB/cpp/explicit_constructor_CPP.aspx
简介
构造函数的确能使你的类变的简单优雅,它也是一个基本的函数,可以由编译器以默认的方式提供给你,即默认构造函数。在c++中,如果你只写一行代码。
Class A{};
编译器会提供给你一个默认的、无参数的构造函数,并伴随一个析构函数,一个拷贝构造函数(copy Constructor),一个拷贝复制操作符(copy assignment operator)
背景
那么什么是显式构造函数?
为了方便理解显式构造函数,我们首先需要理解隐式转换,让我们看一下它在代码中的作用,以及什么时候不需要这些特性。
使用以下代码,例1:思考下面这个传统而简单的复数类:
- #include <iostream>
- using std::cout;
- using std::endl;
- class complexNumbers {
- double real, img;
- public:
- complexNumbers() : real(0), img(0) { }
- complexNumbers(const complexNumbers& c) { real = c.real; img = c.img; }
- complexNumbers( double r, double i = 0.0) { real = r; img = i; }
- friend void display(complexNumbers cx);
- };
- void display(complexNumbers cx){
- cout<<"Real Part: "<<cx.real<<" Imag Part: "<<cx.img<<endl;
- }
- int main() {
- complexNumbers one(1);
- complexNumbers five = 5;
- display(one);
- display(five);
- return 0;
- }
这个复数类很简单,它包括实数复数两部分,代码定义了一个默认的构造函数,一个拷贝构造函数,以及着重定义了另一个构造函数,用它来帮我们做一些隐式的构造。
在main函数中,我们首先创建了一个名为one 和一个名为 five的对象,由于隐式转换的作用,它们都能成功调用。故对象one的实数为1,虚数为 0;对象five的实数为5,虚数0.我们可以使用复数类中的 “display”方法打印出来,对隐式转换的理解,这是一个很好的例子。输出结果如下:
Real Part: 1 Imag Part: 0
Real Part: 5 Imag Part: 0
下面我们考虑这个例子:
- #include <iostream>
- using std::cout;
- using std::endl;
- class complexNumbers {
- double real, img;
- public:
- complexNumbers() : real(0), img(0) { }
- complexNumbers(const complexNumbers& c) { real = c.real; img = c.img; }
- complexNumbers( double r, double i = 0.0) { real = r; img = i; }
- friend void display(complexNumbers cx);
- };
- void display(complexNumbers cx){
- cout<<"Real Part: "<<cx.real<<" Imag Part: "<<cx.img<<endl;
- }
- int main() {
- complexNumbers one(1);
- display(one);
- display(300);
- return 0;
- }
类似的例子,只是在main方法中多加了一行,display(300),继续,输出结果变为:
Real Part: 1 Imag Part: 0
Real Part: 300 Imag Part: 0
“邦”!!!这不是我们希望的结果,首先代码本身就不清楚,display(300)什么意思?display 方法的参数期待的是复数类的一个对象/实例,而300根本不是,那么这种情况是如何发生的呢?
因为display方法期待一个复数类的一个对象/实例,当我们把300这个十进制数传进去是,在将300这个十进制数传到复数类的一个临时对象时,发生了一次隐式转换。(因此,300就赋值给临时对象的实数了)。
那么怎么解决这种情况呢??
很简单,强制编译器只能通过显示构造来创建对象,技巧如下:
- #include <iostream>
- using std::cout;
- using std::endl;
- class complexNumbers {
- double real, img;
- public:
- complexNumbers() : real(0), img(0) { }
- complexNumbers(const complexNumbers& c) { real = c.real; img = c.img; }
- explicit complexNumbers( double r, double i = 0.0) { real = r; img = i; }
- friend void display(complexNumbers cx);
- };
- void display(complexNumbers cx){
- cout<<"Real Part: "<<cx.real<<" Imag Part: "<<cx.img<<endl;
- }
- int main() {
- complexNumbers one(1);
- display(one);
- complexNumbers two =2;
- display(200);
- return 0;
- }
思考下面的语句:
- explicit complexNumbers( double r, double i = 0.0) { real = r; img = i; }
此时我们强制编译器在这段代码中不能使用隐式转换,如果程序员写包含隐式转换的代码,编译器将返回一个错误。
- bash-3.2$ g++ -g -o hello test2.cpp
- test2.cpp: In function ‘int main()’:
- test2.cpp:22: error: conversion from ‘int’ to non-scalar type ‘complexNumbers’ requested
- test2.cpp:23: error: conversion from ‘int’ to non-scalar type ‘complexNumbers’ requested
鉴于此,程序员应当用下面的方法实现:
display(complexNumbers(200)); //只允许显示转换…………
以上是关于C++显式构造函数 [翻译]的主要内容,如果未能解决你的问题,请参考以下文章