C++ Primer Plus的若干收获--(十一)

本篇主要讲了转换函数的利与弊以及简要介绍流与iostream文件

 

因为在本篇仍然要使用上篇的Stonewt类,这里首先给出其代码

<span style="font-size:18px;">ifndef STONEWT_H
using std::cout;
#define STONEWT_H


class Stonewt
{
    public:
        Stonewt(double lbs,int stn);
        {
            stone=stn;
            pds_left=lbs;
            pounds=stn*Lbs_per_stn;
        }
        
        Stonewt(double lbs)
        {
            stone=int(lbs)/Lbs_per_stn;//integer divition
            pds_left=int(lbs)%Lbs_per_stn+lbs-int(lbs);
            pounds=lbs;
        }
        
        stonewt() {stone=pounds=pds_left=0;};
        virtual ~Stonewt() {};
        void show_lbs() const {cout<<pounds<<"pounds
";};
        void show_stn() const {cout<<stone<<"stone,"<<pds_left<<"pounds
";};

    private:
        enum{Lbs_per_stn=14};
        int stone;
        double pds_left;
        double pounds;
};

#endif // STONEWT_H</span>


11.1 转换函数

由上篇我们知道,由隐式转换我们科以把一个double类型的值赋给Stonewt对象,可是,能够做相反的转换吗?也就是

<span style="font-size:18px;">Stonewt wolfe(285.7);
double host=wolfe;//possible??</span>


要进行这样的相反的转换,必须使用特殊的C++运算符函数——转换函数。转换函数是用户定义的强制类型转换,能够像使用强制类型转换那样使用它们。假设定义了转换函数,则能够进行以下的转换

<span style="font-size:18px;">Stonewt wolfe(285.7);
double host=double(wolfe);
double star=(double)wolfe;</span>


11.2 创建转换函数

要转换typename类型,须要使用这样的形式的转换函数

<span style="font-size:18px;">operator typename();</span>

  • 请注意一下几点:
  • 转换函数必须是类方法;
  • 转换函数不能指定返回类型;
  • 转换函数不能有參数。

这里我们能够给出Stonewt的转换函数

<span style="font-size:18px;">Stonewt::operator int() const
{
  return int(pounds+0.5);
}

Stonewt::operator double() const
{
  return pounds;
}</span>


此后,我们写这种语句将是合法的

<span style="font-size:18px;">Stonewt poppins;
long gone=(double)poppins;
long gone=int(poppins);</span>


11.3 转换函数的缺点

和转换构造函数一样,转换函数也有其缺点。提供自己主动运行、隐式转换的函数所存在的问题是:在用户不希望进行转换时,转换函数也可能进行转换。为了避免这样的情况我们能够用explicit。有了例如以下的声明后,需可将运算符声明为显式的

<span style="font-size:18px;">explicit operator int() const;
explicit opreator double() const;</span>


总之,C++为类提供了以下的类型转换:

  • 仅仅有一个參数的类构造函数用于将类型与该參数形同的值转换为类类型。比方,将int值赋给Stonewt对象时,接受int參数的Stonewt类构造函数将自己主动被调用。能够在构造声明中用explicit防止隐式转换。
  • 被称为转换函数的特殊成员运算符函数,用于将类对象转换为其它类型,转换函数是类成员,没有返回值、没有參数、名为operator typename()。将类对象赋给typename变量或将其转换为typename是,该函数将自己主动被调用。

学习了这么多类的知识,一时难以消化,这里最好还是临时转入对文件的输入输出中

11.4 流与缓冲区

C++把输入和输出看做字节流。输入时,程序从输入流中抽取字节;输出时,程序将字节插入到输出流中。输入流中的字节可能来自键盘,也可能来自从初设备或其它程序。相同,输出流中的字节能够流向屏幕、打印机、存储设备或其它设备。流充当了程序和流源或流目标之间的桥梁。

输入流须要两个连接,每端各一个。文件端部连接提供了流的来源,程序端连接将流的输出部分转储到程序中。相同,对输出管理包含将输出流连接到程序以及将输出目标与流关联起来。通常,通过使用缓冲区能够更高效的处理输入和输出。缓冲区是用作中介的内存块,它是将信息从设备传输到程序或从程序传输给设备的暂时存储工具。。通常,像磁盘存储器这样的设备已512字节的块为单位来传输信息,而程序通常每次仅仅能处理一个字节的信息。缓冲的方法则是从磁盘中读取大量的信息,将这些信息存储到缓冲区中,然后从缓冲区中每次读取一个字节。由于从内存中读取数据比从磁盘中块的多,因此这样的方式更高效。

键盘每次提供一个字符,因此在这样的情况下,程序无需缓冲区来帮助匹配不同的传输数据效率。然而,对键盘输入进行缓冲能够让用户在将输入传输给程序之前返回并更正。C++程序通常在用户按下回车时刷新输入缓冲区。这就是为什么程序要到用户按下回车的时候在进行处理。对于屏幕输出,C++程序通常在用户发出换行符是刷新输出缓冲区。

 

11.5 流、缓冲区与iostream文件

管理流和缓冲区的工作有点复杂,iostream包括一些专门的设计来实现管理流和缓冲区的类。

  • streambuf类为缓冲区提供了内存,并提供了用于填充缓冲区、訪问缓冲区内容、刷新缓冲区和管理缓冲区内存的类方法;
  • ios_base类表示流的一半特征,如是否科读取、是二进制还是文本流等;
  • ios类基于ios_base类,当中包含了一个指向streambuf对象的指针成员;
  • ostream类从ios类中派生而来,提供了输出的方法;
  • ostream类也是从ios类派生而来的,提供了输入的方法;
  • iostream类是基于istream和ostream类的,因此继承了输入方法和输出方法。

这里在略微介绍下iostream类库管理的一些细节:

  • cin对象相应于标准输入流。在默认情况下,这个流被关联到标准的输入设备(键盘),wcin,wcout与此类似,可是处理的是wchar_t类型;
  • cout对象与标准输出流相相应。在默认的情况下,这个流被关联在标准的输出设备(显示器)中,wcout对象于此类似,可是处理的是wchar_t类型;
  • cerr对象与标准错误流相相应。在默认情况下,这个流被关联在标准输出设备(显示器)。这个刘没有被缓冲,这意味着信息将被直接发送给屏幕,而不会等到缓冲区填满或是新的换行符。werr语气类似。
  • clog对象也相应于标准错误流。在默认情况下,这个流被关联在标准输出设备(现实器),这个流被缓冲。wclog与此相类似。
  • 对象代表流——这意味这什么呢?当iostream文件为程序声明一个cout对象时,该对象将包含存储了与输出有关的信息的数据成员,如现实数据时使用的字段宽度、小数位数、计数方法以及用来处理缓冲区的streambuf对象的地址。以下的语句是通过是想streambuf对象将字符串中的字符放入到cout管理的缓冲区中
<span style="font-size:18px;">cout<<"bju Masd";
</span>


 

今天状态不是太好(预计是由于今天要回学校,内心一直静不下来),就写这么多了

原文地址:https://www.cnblogs.com/gcczhongduan/p/4502422.html