65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 中的显式构造函数

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (104投票s)

2008 年 8 月 18 日

CPOL

2分钟阅读

viewsIcon

185985

downloadIcon

286

C++ 中的显式构造函数。

引言

构造函数确实让您的类变得简单优雅。构造函数是您的代码的基本基础,编译器会默认提供它。这称为默认构造函数。也就是说,在 C++ 中,如果您只写一行代码

Class A{ };

编译器会为您提供一个默认的零参数构造函数,以及一个析构函数、一个复制构造函数和一个复制赋值运算符。

背景

那么,什么是显式构造函数?

为了理解显式构造,我们需要先理解隐式转换,让我们看看它在编写代码时如何帮助您,以及有时这种特性为何不受欢迎。

使用代码

示例 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<<&quot;Real Part: &quot;<<cx.real<<&quot; Imag Part: &quot;<<cx.img<<endl;
}
int main() {
  complexNumbers one(1);
  complexNumbers five = 5;
  display(one);
  display(five);
  return 0;
}

complexNumbers 类非常简单;它包含两个部分,名为 realimg,分别表示复数的实部和虚部。代码定义了一个默认构造函数、一个复制构造函数,以及最重要的,定义了另一个构造函数,它帮助我们进行隐式构造。

main 中,我们首先创建一个名为“one”的类对象,然后创建另一个名为“five”的对象,这两个调用都成功,因为发生了隐式转换。因此,对于对象“one”,对象的“real”部分变为 1,“img”部分变为 0,对于对象“five”,对象的“real”部分变为 5,而“img”部分变为 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<<&quot;Real Part: &quot;<<cx.real<<&quot; Imag Part: &quot;<<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) 是什么意思?300 本身永远不是方法 display 期望作为参数的 complexNumbers 类的对象/实例。那么,这是怎么发生的?

由于方法 display 期望 complexNumbers 类的对象/实例作为参数,当我们传递十进制值 300 时,会发生隐式转换,进而将十进制值 300 转换为 complexNumbers 类的临时对象(从而将值 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<<&quot;Real Part: &quot;<<cx.real<<&quot; Imag Part: &quot;<<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)); //only explicit conversion is allowed…………
© . All rights reserved.