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

简介:

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.

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

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

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

 

 

 

 

 

 

 

目录
相关文章
|
8月前
|
编译器 C++
C++复习题
C++复习题
31 0
|
10月前
|
编译器 C++
C++ Primer Plus 第十四章答案 C++中的代码重用
只有聪明人才能看见的摘要~( ̄▽ ̄~)~
42 0
|
Java
java编程思想第四版第十一章习题
运行结果分析: 这个案例的重点是, 数组瘦受限制的, 集合是没有元素个数限制的。
181 0
|
存储 Java API
java编程思想第四版第十一章总结
容器类被分为两类:Collection和Map
99 0
|
设计模式 Java
java编程思想第四版第九章习题
输出结果: 调用基类构造方法的时候, 只是给子类的成员变量分配了一块内存空间, 并将内存空间的值设置为默认值0.
80 0
|
Web App开发 网络协议 关系型数据库