tag 标签: 面向对象编程

相关博文
  • 热度 16
    2014-2-17 15:45
    1254 次阅读|
    5 个评论
    类(Classes)       类(class)是一种将数据和函数组织在同一个结构里的逻辑方法。定义类的关键字为 class , 其功能与 C 语言中的 struct 类似 ,不同之处是 class 可以包含函数,而不像 struct 只能包含数据元素。(请注意这里是相对于C语言来说的,C++中struct 和 class关 键字类似,仅在于默认的访问权限不同) 类定义的形式是: class class_name { permission_label_1: member1; permission_label_2: member2; ... } object_name; 其中 class_name 是类的名称 (用户自定义的类型) ,而可选项 object_name 是一个或 几个对象(object)标识。Class 的声明体中包含成员 members,成员可以是数据或函数 定义,同时也可以包括允许范围标志 permission labels,范围标志可以是以下三个关键 字中任意一个:private:, public: 或 protected:。它们分别代表以下含义: •private :class 的 private 成员,只有同一个 class 的其他成员或该 class 的 “friend” class 可以访问这些成员。   •protected :class 的 protected 成员,只有同一个 cl ass 的其他成员,或该 class 的“friend” class,或该 class 的子类(derived classes) 可以访问这些成员。   •public :class 的 public 成员,任何可以看到这个 class 的地方都可以访问这 些成员。 如果我们在定义一个 class 成员的时候没有声明其允许范围,这些成员将被默认为 private 范围。 例如: class CRectangle { int x, y; public: void set_values (int,int); int area (void); } rect; 上面例子定义了一个 class CRectangle 和该 class 类型的对象变量 rect 。这个 class 有 4 个成员:两个整型变量 (x 和 y) ,在 private 部分 (因为 private 是默认的允许 范围);以及两个函数, 在 public 部分:set_values() 和 area(),这里只包含了函 数的原型(prototype)。        注意 class 名称与对象(object)名称的不同:在上面的例子中,CRectangle 是 class 名称 (即用户定义的类型名称),而 rect 是一个 CRectangle 类型的对象名称。它们的区 别就像下面例子中类型名 int 和 变量名 a 的区别一样: Int  a; int 是 class 名称 (类型名) ,而 a 是对象名 object name (变量)。 在程序中,我们可以通过使用对象名后面加一点再加成员名称(同使用 C structs 一样), 来引用对象 rect 的任何 public 成员,就像它们只是一般的函数或变量。例如: rect.set_value (3,4); myarea = rect.area(); 但我们不能够引用 x 或 y ,因为它们是该 class 的 private 成员,它们只能够在该 class 的其它成员中被引用。晕了吗?下面是关于 class CRectangle 的一个复杂的例子: // classes xample #include class CRectangle { int x, y; public: void set_values (int,int); int area (void) {return (x*y);} }; void CRectangle::set_values (int a, int b) { x = a; y = b; } int main () { CRectangle rect; rect.set_values (3,4); cout "area: " rect.area(); } area: 12         上面代码中新的东西是在定义函数 set_values().使用的范围操作符(双冒号:: )。它是 用来在一个 class 之外定义该 class 的成员。注意,我们在 CRectangle class 内部已经 定义了函数 area() 的具体操作,因为这个函数非常简单。而对函数 set_values() ,在 class 内部只是定义了它的原型 prototype,而其实现是在 class 之外定义的。这种在 class 之外定义其成员的情况必须使用范围操作符::。 范围操作符 (::) 声明了被定义的成员所属的 class 名称,并赋予被定义成员适当的范 围属性,这些范围属性与在 class 内部定义成员的属性是一样的。例如,在上面的例子 中,我们在函数 set_values() 中引用了 private 变量 x 和 y,这些变量只有在 class 内部和它的成员中才是可见的。 在 class 内部直接定义完整的函数,和只定义函数的原型而把具体实现放在 class 外部 的唯一区别在于,在第一种情况中,编译器(compiler) 会自动将函数作为 inline 考虑, 而在第二种情况下,函数只是一般的 class 成员函数。 我们把 x 和 y 定义为 private 成员 (记住,如果没有特殊声明,所有 class 的成员均 默认为 private ),原因是我们已经定义了一个设置这些变量值的函数 (set_values()) ,这样一来,在程序的其它地方就没有办法直接访问它们。也许在一个 这样简单的例子中,你无法看到这样保护两个变量有什么意义,但在比较复杂的程序中, 这是非常重要的,因为它使得变量不会被意外修改 (这里意外指的是从 object 的角度 来讲的意外)。        使用 class 的一个更大的好处是我们可以用它来定义多个不同对象(object)。例如, 接着上面 class CRectangle 的例子,除了对象 rect 之外,我们还可以定义对象 rectb : // class xample #include class CRectangle { int x, y; public: void set_values (int,int); int area (void) {return (x*y);} }; void CRectangle::set_values (int a, int b) { x = a; y = b; } int main () { CRectangle rect, rectb; rect.set_values (3,4); rectb.set_values (5,6); cout "rect area: " rect.area() endl; cout "rectb area: " rectb.area() endl; } rect area: 12 rectb area: 30   注意: 调用函数 rect.area() 与调用 rectb.area()所得到的结果是不一样的。这是因为 每一个 class CRectangle 的对象都拥有它自己的变量 x 和 y,以及它自己的函数 set_value() 和 area()。       这是基于对象( object) 和 面向对象编程 (object-oriented programming)的概念的。 这个概念中,数据和函数是对象(object)的属性(properties),而不是像以前在结构化 编程 (structured programming) 中所认为的对象(object)是函数参数。在本节及后面 的小节中,我们将讨论面向对象编程的好处。 在这个具体的例子中,我们讨论的 class (object 的类型)是 CRectangle,有两个实例 (instance),或称对象(object):rect 和 rectb,每一个有它自己的成员变量和成员函 数。 构造函数和析构函数 (Constructors and destructors)       对象(object)在生成过程中通常需要初始化变量或分配动态内存,以便我们能够操作, 或防止在执行过程中返回意外结果。例如,在前面的例子中,如果我们在调用函数 set_values( ) 之前就调用了函数 area(),将会产生什么样的结果呢?可能会是一个不 确定的值,因为成员 x 和 y 还没有被赋于任何值。 为了避免这种情况发生,一个 class 可以包含一个特殊的函数:构造函数 constructor, 它可以通过声明一个与 class 同名的函数来定义。当且仅当要生成一个 class 的新的实 例 (instance)的时候,也就是当且仅当声明一个新的对象,或给该 class 的一个对象分 配内存的时候,这个构造函数将自动被调用。下面,我们将实现包含一个构造函数的 CRectangle : // class xample #include class CRectangle { int width, height; public: CRectangle (int,int); int area (void) {return (width*height);} }; CRectangle::CRectangle (int a, int b) { //构造函数没有返回值 width = a; height = b; } int main () { CRectangle rect (3,4); CRectangle rectb (5,6); cout "rect area: " rect.area() endl; cout "rectb area: " rectb.area() endl; } rect area: 12 rectb area: 30      正如你所看到的,这个例子的输出结果与前面一个没有区别。在这个例子中,我们只 是把函数set_values换成了class的构造函数constructor。注意这里参数是如何在class 实例 (instance)生成的时候传递给构造函数的: CRectangle rect (3,4); CRectangle rectb (5,6); 同时你可以看到,构造函数的原型和实现中都没有返回值(return value),也没有 void 类型声明。构造函数必须这样写。一个构造函数永远没有返回值,也不用声明 void,就 像我们在前面的例子中看到的。          析构函数 Destructor 完成相反的功能。它在 objects 被从内存中释放的时候被自动 调用。释放可能是因为它存在的范围已经结束了(例如,如果 object 被定义为一个函数 内的本地(local)对象变量,而该函数结束了);或者是因为它是一个动态分配的对 象, 而被使用操作符 delete 释放了。 析构函数必须与 class 同名,加水波号 tilde (~) 前缀,必须无返回值。 析构函数特别适用于当一个对象被动态分别内存空间,而在对象被销毁的时我们希望释 放它所占用的空间的时候。例如: // example on constructors and destructors #include class CRectangle { int *width, *height; public: CRectangle (int,int); ~CRectangle (); int area (void) {return (*width * *height);} }; CRectangle::CRectangle (int a, int b) { width = new int; height = new int; *width = a; *height = b; } CRectangle::~CRectangle () { delete width; delete height; } int main () { CRectangle rect (3,4), rectb (5,6); cout "rect area: " rect.area() endl; cout "rectb area: " rectb.area() endl; return 0; } rect area: 12 rectb area: 30   构造函数重载(Overloading Constructors) 像其它函数一样,一个构造函数也可以被多次重载(overload)为同样名字的函数,但有 不同的参数类型和个数。记住,编译器会调用与在调用时刻要求的参数类型和个数一样 的那个函数(Section 2.3, Functions-II)。在这里则是调用与类对象被声明时一样的那 个构造函数。
  • 热度 11
    2014-2-15 15:43
    1409 次阅读|
    1 个评论
    类之间的继承     类的一个重要特征是继承,这使得我们可以基于一个类生成另一个类的对象,以便使后 者拥有前者的某些成员,再加上它自己的一些成员。例如,假设我们要声明一系列类型 的多边形,比如长方形 CRectangle 或三角形 CTriangle。它们有一些共同的特征,比如 都可以只用两条边来描述:高(height)和底(base)。 这个特点可以用一个类 CPolygon 来表示,基于这个类我们可以引申出上面提到的两个 类 CRectangle 和 CTriangle 。 类 CPolygon 包含所有多边形共有的成员。在我们的例子里就是: width 和 height。 而 CRectangle 和 CTriangle 将为它的子类(derived classes)。 由其它类引申而来的子类继承基类的所有可视成员,意思是说,如果一个基类包含成员 A ,而我们将它引申为另一个包含成员 B 的类,则这个子类将同时包含 A 和 B。      要定义一个类的子类,我们必须在子类的声明中使用冒号(colon)操作符: ,如下所示: class derived_class_name: public base_class_name; 这里 derived_class_name 为子类(derived class)名称,base_class_name 为基类(base class)名称。public 也可以根据需要换为 protected 或 private,描述了被继承的成 员的访问权限,// derived classes #include Class CPolygon  //定义一个多边形的基类 { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b;} }; class CRectangle: public CPolygon { public: int area (void) { return (width *height); } }; }; class CTriangle: public CPolygon { public: int area (void){ return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; rect.set_values (4,5); trgl.set_values (4,5); cout rect.area() endl; cout trgl.area() endl; return 0; } 输出结果: 20 10 标识符 protected 与 private 类似,它们的唯一区别在继承时才表现出来。当定义一个 子类的时候,基类的 protected 成员可以被子类的其它成员所使用,然而 private 成员就不 可以。因为我们希望 CPolygon 的成员 width 和 height 能够被子类 CRectangle 和 CTriangle 的成员所访问,而不只是被CPolygon自身的成员操作,我们使用了protected 访问权限,而不是 private。 下表按照谁能访问总结了不同访问权限类型: 可以访问      public  protected  private  本 class 的成员  yes  yes  yes  子类的成员  yes  yes  no  非成员  yes  no  no  这里"非成员"指从 class 以外的任何地方引用,例如从 main()中,从其它的 class 中或从全域(global)或本地(local)的任何函数中。 在我们的例子中,CRectangle 和 CTriangle 继承的成员与基类 CPolygon 拥有同样的访 问限制: CPolygon::width          // protected access CRectangle::width         // protected access CPolygon::set_values()     // public access CRectangle::set_values()   // public access 这是因为我们在继承的时候使用的是 public,记得我们用的是:class CRectangle: public CPolygon; 这里关键字 public 表示新的类(CRectangle)从基类(CPolygon)所继承的成员必须获得 最低程度保护。即从基本类中继承的成员将会是public的权限。这种被继承成员的访问限制的最低程度可以通过使用 protected 或 private 而不是 public 来改变。 最常用的继承限制除了 public 外就是 private ,它被用来将基类完全封装起来,因为 在这种情况下,除了子类自身外,其它任何程序都不能访问那些从基类继承而来的成员。 不过大多数情况下继承都是使用 public 的。   如果没有明确写出访问限制,所有由关键字 class 生成的类被默认为 private ,而所有 由关键字 struct 生成的类被默认为 public。 基类中继承 理论上说,子类(drived class)继承了基类(base class)的所有成员,除了: •构造函数 Constructor 和析构函数 destructor •operator=() 成员 •friends 虽然基类的构造函数和析构函数没有被继承,但是当一个子类的 object 被生成或销毁的 时候,其基类的默认构造函数 (即,没有任何参数的构造函数)和析构函数总是被自动调 用的。 如果基类没有默认构造函数,或你希望当子类生成新的 object 时,基类的某个重载的构 造函数被调用,你需要在子类的每一个构造函数的定义中指定它: derived_class_name (parameters) : base_class_name (parameters) {} 例如 : // constructors and derivated classes #include iostream.h class mother { public: mother () { cout "mother: noparameters\n"; } mother (int a) { cout "mother: intparameter\n" } }; class daughter : public mother { public: daughter (int a)    //这里没写,将调用默认的构造函数 { cout "daughter: intparameter\n\n"; } };   class son : public mother  { public: son (int a) : mother (a)   //在这里指定了构造函数 { cout "son: intparameter\n\n"; } }; int main ()  { daughter cynthia (1); son daniel(1); return 0; }   mother: no parameters daughter: int parameter mother: int parameter son: int parameter   观察当一个新的 daughter object 生成的时候 mother 的哪一个构造函数被调用了,而当 新的 son object 生成的时候,又是哪一个被调用了。不同的构造函数被调用是因为 daughter 和 son 的构造函数的定义不同: daughter (int a) // 没有特别制定:调用默认 constructor son (int a) : mother (a) // 指定了 constructor: 调用被指定的构造函数   多重继承 (Multiple inheritance) 在 C++ 中,一个 class 可以从多个 class 中继承属性或函数,只需要在子类的声明中用 逗号将不同基类分开就可以了。例如,如果我们有一个特殊的 class COutput 可以实现 向屏幕打印的功能,我们同时希望我们的类 CRectangle 和 CTriangle 在 CPolygon 之 外还继承一些其它的成员,我们可以这样写: class CRectangle: public CPolygon, public COutput { class CTriangle: public CPolygon, public COutput { 以下是一个完整的例子: // multiple inheritance #include iostream.h class CPolygon  { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b;} }; class COutput  { public: void output (int i); }; void COutput::output (int i) { cout i endl; } class CRectangle: public CPolygon, public COutput { public: int area (void) { return (width * height); } }; class CTriangle: public CPolygon, public COutput { public: int area (void) { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; rect.set_values (4,5); trgl.set_values (4,5); rect.output (rect.area()); trgl.output (trgl.area()); return 0; }   结果是: 20 10  
  • 热度 12
    2014-2-15 09:32
    944 次阅读|
    0 个评论
    类之间的关系 (Relationships between classes)   1.友元函数 (Friend functions)      前面的章节中我们已经看到了对 class 的不同成员存在 3 个层次的内部保 护: public , protected 和 private。 在成员为 protected 和 private 的情况下,它们 不能够被从 所在的 class 以外的部分引用。然而,这个规则可以通过在一个 class 中使 用关键字 friend 来绕过,这样我们可以允许一个外部函数获得访问 class 的 protected 和 private 成员的能力。     为了实现允许一个外部函数访问 class 的 private 和 protected 成员,我们必须在 class 内部用关键字 friend 来声明该外部函数的原型,以指定允许该函数共享 class 的 成员。在下面的例子中我们声明了一个 friend 函数 duplicate : // friend functions #include class CRectangle { int width, height; public: void set_values (int, int); int area (void) {return (width * height);} friend CRectangle duplicate (CRectangle); // 声明一个友元函数 duplicate 返回值和 输入参数为 CRectangle类型 }; void CRectangle::set_values (int a, intb) { width = a; height = b; } CRectangle duplicate (CRectangle  rectparam) //该函数并没有将其范围限定为 CRectangle { CRectangle rectres; rectres.width = rectparam.width*2; rectres.height = rectparam.height*2; return (rectres); } int main ()  { CRectangle rect, rectb; rect.set_values (2,3); rectb = duplicate (rect); cout rectb.area(); } 函数 duplicate 是 CRectangle 的 friend ,因此在该函数之内,我们可 以 访问 CRectangle 类型的各个 object 的成员 width 和 height 。注意 在 duplicate() 的声明中,及其在后面 main() 里被调用的时候,我们并没有 把 duplicate 当作 class CRectangle 的成员, 它并不是。 friend 函数可以被用来实现两个不同 class 之间的操作。广义来说, 使 用 friend 函数 是面向对象编程之外的方法,因此,如果可能,应尽量使 用 class 的成员函数来完成这 些操作。比如在以上的例子中,将函数 duplicate() 集成在 class CRectangle 可以使 程序更短。 友元类 (Friend classes) 就像我们可以定义一个 friend 函数,我们也可以定义一个 class 是另一个的 friend , 以便允许第二个 class 访问第一个 class 的 protected 和 private 成员。 // friend class   #include class CSquare; class CRectangle { int width, height; public: int area (void) {return (width * height);} void convert (CSquare a); }; Class CSquare { private: int side; public: void set_side (int a){side=a;} friend class CRectangle; // CRectangle 是 CSquare 的友元类 }; void CRectangle::convert (CSquare a) // 在此利用友元类实现了复制参数的功能 { width = a.side; height = a.side; } int main () { CSquare sqr; CRectangle rect; sqr.set_side(4); rect.convert(sqr); cout rect.area(); return 0; } 结果: 16 在这个例子中,我们声明了 CRectangle 是 CSquare 的 friend ,因此 CRectangle 可以 访问 CSquare 的 protected 和 private 成员,更具体地说,可以访问 CSquare::side , 它定义了正方形的边长。 在上面程序的第一个语句里你可能也看到了一些新的东西,就是 class CSquare 空原型。 这是必需的,因为在 CRectangle 的声明中我们引用了 CSquare ( 作为 convert() 的参 数 ) 。 CSquare 的定义在 CRectangle 的后面,因此如果我们没有在这个 class 之前包含 一个 CSquare 的声明,它在 CRectangle 中就是不可见的。    这里要考虑到,如果没有特别指明,友元关系( friendships )并不是相互的。在我们 的 CSquare 例子中, CRectangle 是一个 friend 类,但因为 CRectangle 并没有对 CSquare 作相应的声明,因此 CRectangle 可以访问 CSquare 的 protected 和 private 成员, 但反过来并不行,除非我们将 CSquare 也定义为 CRectangle 的 friend 。
  • 热度 9
    2014-2-14 10:01
    1091 次阅读|
    0 个评论
    四.控制台交互(Communication through console) 在 C++的 iostream 函数库中,一个程序的标准输入输出操作依靠两种数据流:cin 给输入使用和 cout 给输出使用。另外,cerr 和 clog 也已经被实现――它们是两种特殊设计的数据流专门用来显示出错信息。它们可以被重新定向到标准输出设备或到一个日志文件(log file)。 因此 cout (标准输出流)通常被定向到屏幕,而 cin (标准输入流)通常被定向到键盘。 通过控制这两种数据流,你可以在程序中与用户交互,因为你可以在屏幕上显示输出并从键盘接收用户的输入。   1.输出 Output (cout) 输出流 cout 与重载(overloaded)运算符一起使用: cout "Output sentence"; // 打印 Output sentence 到屏幕上 cout 120; // 打印数字 120 到屏幕上 cout x; // 打印变量 x 的值到屏幕上 运算符又叫插入运算符(insertion operator) 因为它将后面所跟的数据插入到它前面的数据流中。在以上的例子中,字符串常量 Output sentence,数字常量 120 和变量 x先后被插入输出流 cout 中。注意第一句中字符串常量是被双引号引起来的。每当我们使用字符串常量的时候,必须用引号把字符串引起来,以便将它和变量名明显的区分开来。 例如,下面两个语句是不同的: cout "Hello"; // 打印字符串 Hello 到屏幕上 cout Hello; // 把变量 Hello 存储的内容打印到屏幕上 插入运算符 insertion operator ()可以在同一语句中被多次使用: cout "Hello, " "I am " "a C++ sentence"; 上面这一行语句将会打印 Hello, I am a C++ sentence 到屏幕上。插入运算符() 的 重复使用在我们想要打印变量和内容的组合内容或多个变量时有所体现: cout "Hello, I am " age " years old and my zipcode is " zipcode; 如果我们假设变量 age 的值为 24,变量 zipcode 的值为 90064,以上句子的输出将为: Hello, I am 24 years old and my zipcode is 90064 必须注意,除非我们明确指定,cout 并不会自动在其输出内容的末尾加换行符,因此下 面的语句: cout "This is a sentence."; cout "This is another sentence."; 将会有如下内容输出到屏幕: This is a sentence.This is another sentence. 虽然我们分别调用了两次 cout,两个句子还是被输出在同一行。所以,为了在输出中换 行,我们必须插入一个换行符来明确表达这一要求。在 C++中换行符可以写作\n: cout "First sentence.\n "; cout "Second sentence.\nThird sentence."; 将会产生如下输出: First sentence. Second sentence. Third sentence. 另外,你也可以用操作符 endl 来换行,例如: cout "First sentence." endl; cout "Second sentence." endl; 将会输出: First sentence. Second sentence. 当操作符 endl 被用在 buffered streams 中时有一点特殊:它们被 flushed。不过 cout 默认为 unbuffered,所以不会被影响。 你可以暂时不管这一点。 你可以使用\n 或 endl 来指定 cout 输出换行,请注意前面所讲的两者的不同用法。   输入 Input (cin) C++中的标准输入是通过在 cin 数据流上重载运算符 extraction () 来实现的。它后必须跟一个变量以便存储读入的数据。例如: int age; cin age; 声明一个整型变量 age 然后等待用户从键盘输入到 cin 并将输入值存储在这个变量中。 cin 只能在键盘输入回车键(RETURN)后才能处理前面输入的内容。因此即使你只要求输入一个单独的字符,在用户按下回车键(RETURN)之前 cin 将不会处理用户的输入的字符。在使用 cin 输入的时候必须考虑后面的变量类型。如果你要求输入一个整数,extraction() 后面必须跟一个整型变量,如果要求一个字符,后面必须跟一个字符型变量,如果求一个字符串,后面必须跟一个字符串型变量。 // i/o example Please enter an integer 31/ 170 #include int main () { int i; cout "Please enter an integer value: "; cin i; cout "The value you entered is " i; cout " and its double is " i*2 ".\n"; return 0; } value: 702 The value you entered is 702 and its double is 1404. 使用程序的用户可以使引起错误的原因之一,即使是在最简单的需要用 cin 做输入的程序中(就像我们上面看到的这个程序)。因为如果你要求输入一个整数数值,而用户输入了一个名字(一个字符串),其结果可能导致程序产生错误操作,因为它不是我们期望从用户处获得的数据。当你使用由 cin 输入的数据的时候,你不得不假设程序的用户将会完全合作而不会在程序要求输入整数的时候输入他的名字。后面当我们看到怎样使用字符串的时候,我们将会同时看到一些解决这一类出错问题的办法。 你也可以利用 cin 要求用户输入多个数据 : cin a b; 等同于: cin a; cin b; 在以上两种情况下用户都必须输入两个数据,一个给变量 a,一个给变量 b。输入时两个 变量之间可以以任何有效的空白符号间隔,包括空格,跳跃符 tab 或换行。   cin 和字符串 我们可以像读取基本类型数据一样,使用 cin 和操作符来读取字符串,例如: cin mystring; 但是,cin 只能读取一个单词,一旦碰到任何空格,读取操作就会停止。在很多时候 这并不是我们想要的操作,比如我们希望用户输入一个英文句子,那么这种方法就无法读取完整的句子,因为一定会遇到空格。 要一次读取一整行输入,需要使用 C++的函数 getline,相对于是用 cin,我们更建议使用 getline 来读取用户输入。 例如: // 读取字符串例子 #include #include using namespace std; int main () { string mystr; cout "What's your name? "; getline (cin, mystr); cout "Hello " mystr ".\n"; cout "What is your favorite color? "; getline (cin, mystr); cout "I like " mystr " too!\n"; return 0; } 结果: What's your name? Aqua Hello Aqua. What is your favorite color? blue I like blue too! 你可能注意到在上面的例子中,两次调用 getline 函数我们都是用了同一个字符串变量(mystr)。在第二次调用的时候,程序会自动用第二次输入的内容取代以前的内容。 字符串流 标准头文件 定义了一个叫做 stringstream 的类,使用这个类可以对基于 字符串的对象进行像流(stream)一样的操作。这样,我们可以对字符串进行抽取和插入操作,这对将字符串与数值互相转换非常有用。例如,如果我们想将一个字符串转换为一个整数,可以这样写: string mystr ("1204"); int myint; stringstream(mystr) myint; 这个例子中先定义了一个字符串类型的对象 mystr,初始值为"1204",又定义了一个整数变量 myint。然后我们使用 stringstream 类的构造函数定义了这个类的对象,并以字符串变量 mystr 为参数。因为我们可以像使用流一样使用 stringstream 的对象,所我们可以像使用 cin 那样使用操作符 后面跟一个整数变量来进行提取整数数据。这段代码执行之后变量 myint 存储的是数值 1204 。 // 字符串流的使用示例 #include #include #include using namespace std; int main () { string mystr; float price=0; int quantity=0; cout "Enter price: "; getline (cin,mystr);    //输入字符串形式的Price stringstream(mystr) price; //转换为浮点类型 cout "Enter quantity: "; getline (cin,mystr); //输入字符串形式的quantity stringstream(mystr) quantity;//转换为浮点类型 cout "Total price: " price*quantity endl; return 0; } Enter price: 22.25 Enter quantity: 7 Total price: 155.75 在这个例子中,我们要求用户输入数值,但不同于从标准输入中直接读取数值,我们使用函数 getline 从标注输入流 cin 中读取字符串对象(mystr),然后再从这个字符串对象中提取数值 price 和 quantity。 通过使用这种方法,我们可以对用户的输入有更多的控制,因为它将用户输入与对输入的解释分离,只要求用户输入整行的内容,然后再对用户输入的内容进行检验操作。这种做法在用户输入比较集中的程序中是非常推荐使用的。
相关资源
  • 所需E币: 5
    时间: 2022-3-1 13:57
    大小: 3.55MB
    上传者: 西风瘦马
    《Python3面向对象编程(第2版)》.pdf内容简介本书主要介绍如何使用Python3进行面向对象编程。第1~4章介绍面向对象这一编程范式的基本准则,以及Python是如何运用这些准则实现面向对象编程的;第5~8章介绍如何利用Python中的内置函数快速、简单地实现面向对象编程;第9~11章介绍许多面向对象编程中常用的设计模式,以及如何使用符合Python语言习惯的方式来实现这些设计模式;最后,第12、13章介绍Python3中与并发编程相关的主题。本书中的每一章都会包含一节案例学习的内容,通过一个实践相关的案例将本章介绍的主要内容以及前面章节中介绍过的内容串联起来。除此之外,每一章最后的练习旨在指导你利用本章学习到的知识,使用面向对象编程改善以往项目中的代码,并进一步掌握如何在合适的时机使用Python3进行面向对象编程。Copyright©2015PacktPublishing.FirstpublishedintheEnglishlanguageunderthetitle‘Python3Object-orientedProgramming,SecondEdition(9781784398781)’.本书简体中文版专有出版权由PacktPublishing授予电子工业出版社。未经许可,不得以任何方式复制或抄袭本书的任何部分。专有出版权受法律保护。版权贸易合同登记号图字:01-2015-7448图书在版编目(CIP)数据Python3面向对象编程:第2版/(加)达斯帝·菲利普斯(DustyPhillips)著;孙雨生译.—北京:电子工业出版社,2018.6书名原文:Python3Object-orientedProgramming,SecondEditionISBN978-7-121-34136-6
  • 所需E币: 0
    时间: 2020-9-18 20:51
    大小: 72.55KB
    上传者: LGWU1995
    利用LabVIEW工程库实现面向对象编程
  • 所需E币: 0
    时间: 2020-9-10 03:41
    大小: 98KB
    上传者: Goodluck2020
    77.利用LabVIEW工程库实现面向对象编程.doc
  • 所需E币: 0
    时间: 2020-9-7 17:35
    大小: 52.41MB
    上传者: stanleylo2001
    JavaScript面向对象编程指南.pdf