(一三四)第十二章复习题

1.假设String类有如下私有成员:

class String

{
private:

char*str; //points to string allocated by new

//...

};

a.下述默认构造函数有什么问题?

String::String(){}

b.下述构造函数有什么问题?

String::String(const char* s)
{
str=s;

len=strlen(s);

}

c.下述构造函数有什么问题?

String::String(const char*a)
{
strcpy(str,s);

len=strlen(s);

}

答:

a的问题在于,char*str由于需要通过new来分配内存,因此构造函数、复制构造函数、析构函数,都有对应的new或者delete。而这里至少需要声明是空指针,才可以,否则在遇见delete时,会提示出错。

b的问题在于str不能直接指向传递的字符串s。这可能导致多个对象指向同一个内存地址,或者指向一个由new分配的内存地址但这个地址之后又被delete释放(因此使用该对象会出错)。而len这行代码应该放在最先。

c的问题在于,应该先用len=strlen(s),然后str=new char[len+1];,然后再使用strcpy()函数。

 

 

 

2.如果您定义了一个类,其指针成员是使用new初始化的,请指出可能出现的3个问题,以及如何纠正这些问题。

答:

可能①:只有一个构造函数使用了new来分配,其他比如默认构造函数、复制构造函数、构造函数未使用new来分配内存。

解决:应同时都使用。

可能②:析构函数没有使用delete释放内存。

解决:析构函数应该使用delete释放内存。

可能③:未自定义默认赋值运算符(面向对象的)。

解决:赋值运算符应自定义,且使用new来分配内存,strcpy()函数来拷贝字符串内容。

可能④:指针直接指向某作为参数的字符串。

解决:指针应该指向由new分配,由strcpy()拷贝后的内存地址。

 

 

 

 

3.如果没有显式的提供类方法,编译器将自动生成哪些类方法?请描述这些隐式生成的函数的行为。

答:

①默认构造函数。无赋值,单纯初始化各个数据成员;

②析构函数。无任何操作;

③复制构造函数。按值将被复制的对象传递给被初始化的对象;

④赋值运算符(把一个对象赋值给另一个对象的)。逐成员赋值传递;

⑤地址运算符。(返回this指针的值)

 

 

 

 

4.找出并改正下述类声明中的错误:

class nifty

{

//data

char personality[];

int talents;

//methods

nifty();

nifty(char*s);

ostream & operator<<(ostream&os, nifty&n);

}

 

nifty:nifty()
{

personality=NULL;

talents=0;

}

 

nifty:nifty(char*s)

{

personality = new char [strlen(s)];

personality =s;

talents = 0;

}

ostream & nifty:operator<<(ostream & os, nifty &n)

{

os<<n;

}

 

答:

错误0:类名首字母一般大写,但不是强制规定。

错误①:看上下文,char personality[]应该想要声明的是char指针,而不是一个不确定字符数的字符串,因此应该用char * personality;  char指针和字符串占用的内存空间是不一样的

错误②:公共部分没有写public,在类方法和数据之间加上。

错误③:ostream&那个函数,应该是友元函数,应该在之前加上friend

错误④:作用域解析运算符是“::”,而不是“:”,两个类方法都应该加上。

错误⑤:nifty::nifty(char*s)看意思是要复制指针的字符串给自己。一是new分配的空间少1,二是没有正确使用拷贝,三不太确定talents要初始化为什么,貌似是要初始化为0。因此修改为:

nifty::nifty(char * s)

{

personality = new char[strlen(s)+1];

strcpy(personality, s);

talents=0;

}

错误⑥友元函数无需加作用域解析运算符,函数内部写错。应该改为:

ostream & operator<<(ostream & os, nifty & n)

{

os<<n.personality <<"," <<n.talents;

}

错误⑦类定义结束后没有分号

错误⑧nifty:nifty(char*s)一般写成nifty::nifty(const char *s)

错误⑨ostream & nifty:operator<<(ostream & os, nifty &n)

一般写为:ostream & nifty:operator<<(ostream & os, const nifty &n)——加上cosnt

 

 

 

 

 

5.对于下面的类声明:

class Golfer

{

private:

char * fullname; // points to string containing golfer's name

int games; // holds number of golf games played

int * scores; // points to first element of array of golf scores

public:

Golfer();

Golfer(const char * name, int g=0);

//creates empty dynamic array of g elements if g > 0

Golfer(const Golfer & g);

~Golfer();

};

a.下面各条语句将调用哪些类方法

Golfer nacy; //#1

Golfer lulu("Little Lulu"); //#2

Golfer roy("Roy Hobbs",12); //#3

Golfer * par = new Golfer; //#4

Golfer next = lulu; //#5

Golfer hazzard = "Weed Thwacker"; //#6

*par = nancy; //#7

nancy = "Nancy Putter"; //#8

b.很明显,类需要有另外几个方法才能更有用,但是,类需要哪些方法才能防止数据被损坏呢?

 

答:

a.

1#将调用默认构造函数Golfer()

2#将调用构造函数Golfer(const char * name, int g=0);

3#将调用构造函数Golfer(const char * name, int g=0);

4#将调用默认构造函数Golfer();

5#将调用复制构造函数Golfer(const Golfer & g);

6#将调用构造函数Golfer(const char * name, int g=0);

7#将什么也不调用,单纯将指针指向类对象。

7#将调用赋值运算符(隐式生成的),我没注意到par指针在4#声明了

8#将调用构造函数Golfer(const char * name, int g=0);和隐式生成的赋值运算符

 

b.

为了防止数据损坏,有以下方法:

①防止拷贝,将赋值运算符(面向对象拷贝给对象的)/复制构造函数,放在私有部分;

②自定义赋值运算符/复制构造函数,让其在复制的时候,避免按值传递,让其通过new、strcpy()函数等方式拷贝数据。

 

 

 

 

 

 

 

时间: 2024-09-27 08:58:16

(一三四)第十二章复习题的相关文章

第十二章 委托[《.net框架程序设计》读书笔记]

.net框架|笔记|程序|设计 第十二章 委托 一. 委托的使用 静态委托和实例委托,使用方法类似,这里给出一个使用可变参数委托的例子: using System; public class DelCls { public delegate void DelDef(params string[] strParams); public static void CallDel(DelDef dd) { if(dd != null) //请务必在此处进行判断,这是个好习惯 { dd("Hello&qu

Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验

Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 这一章很多,但是很有趣,也是这书的最后一章知识点了,我现在还在考虑要不要写这个拼图和2048的案例,在此之前,我们先来玩玩Android5.X的新特性吧!

python 教程 第二十二章、 其它应用

第二十二章. 其它应用 1)    Web服务 ##代码 s 000063.SZ ##开盘 o 26.60 ##最高 h 27.05 ##最低 g 26.52 ##最新 l1 26.66 ##涨跌 c1 -0.04 ##涨幅 p2 -0.15% ##总手 v 9190865 ##日期 d1 6/15/2011 ##时间 t1 3:00am #!/usr/bin/env python from time import ctime from urllib import urlopen import

【PMP】Head First PMP 学习笔记 第十二章 采购管理

第十二章 采购管理 某些工作就是太大,以至于你的公司无法自行完成. 找到合适的卖方,选择正确类型的关系并确保合同的目标被打成. 有时候,你需要雇用外部公司做一部分的项目工作.这叫做采购(procurement),该外部公司被称为卖方. 项目采购管理包括合同管理和变更控制过程 规划采购管理 实施采购 控制采购 结束采购 项目采购管理围绕包括合同在内的协议来进行.协议是买卖双方之间的法律文件. 合同也可称作协议.谅解.分包合同或订购单. 在合同生命周期中,卖方首先是投标人.然后是中标人,之后是签约供

python 教程 第十二章、 标准库

第十二章. 标准库 See Python Manuals ? The Python Standard Library ? 1)    sys模块 import sys if len(sys.argv) < 2: print 'No action specified.' sys.exit() if sys.argv[1].startswith('--'): option = sys.argv[1][2:] if option == 'version': print 'Version 1.2' el

第十二章——SQLServer统计信息(3)——发现过期统计信息并处理

原文:第十二章--SQLServer统计信息(3)--发现过期统计信息并处理 前言:         统计信息是关于谓词中的数据分布的主要信息源,如果不知道具体的数据分布,优化器不能获得预估的数据集,从而不能统计需要返回的数据.         在创建列的统计信息后,在DML操作如insert.update.delete后,统计信息就会过时.因为这些操作更改了数据,影响了数据分布.此时需要更新统计信息.         在高活动的表中,统计信息可能几个小时就会过时.对于静态表,可能几个星期才会过

第十二章——SQLServer统计信息(2)——非索引键上统计信息的影响

原文:第十二章--SQLServer统计信息(2)--非索引键上统计信息的影响 前言:         索引对性能方面总是扮演着一个重要的角色,实际上,查询优化器首先检查谓词上的统计信息,然后才决定用什么索引.一般情况下,默认会在创建索引时,索引列上均创建统计信息.但是不代表在非索引键上的统计信息对性能没有用.         如果表上的所有列都有索引,那么将会是数据库负担不起,同时也不是一个好想法,包括谓词中用到的所有列加索引同样也不是好方法.因为索引会带来负载.因为需要空间存放索引,且每个D

第十二章——SQLServer统计信息(4)——在过滤索引上的统计信息

原文:第十二章--SQLServer统计信息(4)--在过滤索引上的统计信息 前言:         从2008开始,引入了一个增强非聚集索引的新功能--过滤索引(filter index),可以使用带有where条件的语句来创建非聚集索引,过滤掉不需要的数据,降低索引的维护开销和存储空间,提高查询性能.   准备工作: 在AdventureWorks2012上,有一个Production.WorkOrder表,将使用这个表来做演示.   步骤: 1.  创建一个非聚集索引在Production

第十二章——SQLServer统计信息(1)——创建和更新统计信息

原文:第十二章--SQLServer统计信息(1)--创建和更新统计信息 简介: 查询的统计信息: 目前为止,已经介绍了选择索引.维护索引.如果有合适的索引并实时更新统计信息,那么优化器会选择有用的索引供查询之用,因为SQLServer优化器是基于开销的优化.当在where和on上的列上的数据需要显示在结果集的时候,如果有实时的统计信息,优化器会选择最好的执行方式,因为优化器会从统计信息中获得这些数据的明细情况. 在创建索引的时候,SQLServer就会在索引列上创建统计信息.简单来说,统计信息