C++Primer 第12章-类和数据抽象-课后习题答案

更新时间:2023-10-06 00:39:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第十二章 类和数据抽象

12.1 编写一个名为person的类,表示人的名字和地址,使用string来保存每个元素。 答:

class person { public: person( string pName, string pAddress )

{ name = pName; address = pAddress; }

private: string name; string address; };

12.2 为person提供一个接收两个string参数的构造函数。 见第一题。

12.3 提供返回名字和地址的操作。这些函数应为const吗?解释你的选择。 在public里添加成员函数: string get_name() const { return name; ] string get_address() const { return address; ] 这两个成员函数不应该修改其操作的对象的数据成员的值,应该声明为const类型。

12.4 指明person的哪个成员应声明为public,哪个成员应声明为private。解释。

数据成员name和address应为private, 保证只能被类的成员所用,外界不可访问。成员函数get_name()和get_address() 应声明为public,为外界提供接口访问类的数据成员。构造函数也应声明为public,以便初始化类的对象。

12.5 C++类支持哪些访问标号? 在每个访问标号之后应定义哪种成员?如果有的话,在类的定义中,一个访问标号可以出现在何处以及可出现多少次?约束条件是什么?

有 public, private, protect。public后定义可被外界访问的接口,private后定义只能被本类成员函数使用的成员;protect后定义的成员称为受保护成员,只能由本类及本类的子类访问。 访问标号可以出现在任意成员定义之前且次数没有限制。 约束条件是:每个访问标号指定了随后的成员定义级别,这个级别持续有效,直到下一个访问标号出现,或者看到类定义体的右花括号为止。

12.6 用class关键字定义的类和用struct定义的类有什么不同。 默认访问标号不同,用struct关键字定义的,在第一个访问标号之前的成员是共有的,如果是用class关键字定义的,在第一个访问标号之前的成员是private成员。 12.7 什么事封装? 为什么封装是有用的? 封装是一种将低层次的元素组合起来形成新的、高层次实体的技术。例如,函数是封装的一种形式:函数所执行的细节行为被封装在函数本身这个更大的实体中。被封装的元素隐藏了它们的实现细节,可以调用一个函数但不能访问它所执行的语句,同样类也是一个封装的实体:它代表若干成员的聚集,大多数类类型隐藏了实现该类型的成员。 封装隐藏了内部元素的实现细节,提供了优点:避免类内部出现无意的 可能破坏对象状态的用户级错误;在修改类的实现时不需要修改用户级代码,这些都很有用。

12.8 将sales_item::avg_price定义为内联函数。 inline double sales_item::avr_price() const { if ( units_sole ) return revenue/units_sold; else return 0; }

12.9 修改本节中给出的screen类,给出一个构造函数,根据屏幕的高度、宽度和内容的值来创建screen。 class Screen {

public: typedef std::string::size_type index; Screen( index hei, index wid , string content ) { contents = content; height = hei; width = wid; } private: std::string contents; index cursor; index height, width; };

12.10 解释下述类中的每个成员: class Record { typedef std::size_t size; Record(): byte_count(0) {} Record(size s): byte_count(s) { } Record(std::stirng s): name(s), byte_count(0) {}

size byte_count; std::string name; public: size get_count() const { return byte_count; } std::string get_name() const { return name; } }; 三个Record()函数是重载的三个构造函数,size byte_count; std::string name;这是两个private的数据成员, size get_count() const , std::string get_name() const 这是两个public成员函数。

12.11 定义两个类X和Y,X中有一个指向Y的指针,Y中有一个X类型的对象。 class Y; class X { Y *p; };

class Y { X xobj; };

12.12 解释类声明与类定义之间的差异。何时使用类声明?何时使用类定义? 类声明是不完全类型,只能以有限方式使用,不能定义该类型的对象,只能用于定义指向该类型的指针及引用,或者声明使用该类型作为形参类型或返回类型的函数。 类定义,一旦类被定义,我们就可以知道所有类的成员,以及存储该类的对象所需的存储空间。 在创建类的对象之前或者使用引用或指针访问类的成员之前必须定义类。

12.13 扩展screen类以及包含move.set和display操作。通过执行如下表达式来测试类: myScreen.move( 4, 0 ).set ( ‘#’ ).display( cout );

// 12.13_Screen.cpp : 定义控制台应用程序的入口点。 //

#include \#include #include

using namespace std;

class Screen {

public: typedef std::string::size_type index; Screen( index hei, index wid , const string &content =\ \ ) {

cursor = 0; contents = content; height = hei; width = wid; } // add 3 new members Screen & move(index r, index c) { index row = r * width; cursor = row + c; return *this; } Screen & set(char c ) { contents[cursor] = c; return *this; } Screen & display( ostream &os ) { do_display(os); return *this; } const Screen & display(ostream &os ) const { do_display(os); return *this; } private: std::string contents; index cursor; index height, width; void do_display(ostream & os) const { os << contents; } };

int _tmain(int argc, _TCHAR* argv[]) { Screen myscreen( 5, 5, \); myscreen.move(4,0).set('#').display(cout); system(\); return 0; }

12.14 通过this指针引用成员虽然合法,但却是多余的。讨论显示地使用this指针访问成员的优缺点。 优点:当需要将一个对象作为整体引用而不是引用对象的一个成员时,使用this,则该函数返回对调用该函数的对象的引用。 可以非常明确地指出访问的是调用该函数的对象的成员,且可以在成员函数中使用与数据成员同名的形参。 缺点:不必要使用,代码多余。

12.15 列出在类作用域中的程序文本部分。 类的定义体;在类外定义的成员函数:形参表、成员函数体,但不包含函数的返回类型。

12.16 如果定义get_cursor时,将会发生什么? Index Screen::get_cursor() const { return cursor; } 编译错误,index是在Screen类的作用域之外的,在类外没有定义index类型。

12.17 如果将Screen类中的类型别名放到类中的最后一行,将会发生什么? 发生编译错误,因为Index的使用出现在了其定义之前。

12.18 解释下述代码,指出每次使用Type或initVal时用到的是哪个名字定义。如果存在错误,说明如何改正。 Typedef string type; Type initVal();

class Exercise { public: // ...

typedef double Type; Type setVal(Type); Type initVal(); private: int val; };

Type Exercise::setVal(Type parm) { val = parm + initVal(); }

本文来源:https://www.bwwdw.com/article/bbpd.html

Top