学习到这里,C++可以说,已经进入一个既是基础的地方,也是高深的地方。
可能你做了几年开发,都没有接触到这些东西,但是又在潜移默化地使用着。
从现在开始,所有题目都打出来。方便查看了。
12.9 复习题
1.假设String类有如下私有成员:
class String
{
private:
char * str;
int len;
};
a.下述默认构造函数有什么问题?
String::String(){}
str没有获得内存,len也没有初始化。所有的都是不确定的。str应该设置为NULL,或者用new[]初始化,len设置相应的值。
b.下述构造函数有什么问题?
String::String(const char * s)
{
str = s;
len = strlen(s);
}
这个只是把s指向的地址放到str。它们是指向同一个内存。如果s被释放了,就出错了。应该使用new[]和strcpy().
c.下述构造函数有什么问题?
String::String(const char* s)
{
strcpy(str, s);
len = strlen(s);
}
str没有分配到内存,应该使用new char[len + 1]来分配适当的内存。
2.如果您定义了一个类,其指针成员是使用new初始化的,请指出可能出现的3个问题以及如何纠正这些问题。
a.析构函数没有对指针成员指向的内存进行释放
在析构函数里delete
b.复制或者赋值的时候,直接复制地址,没有进行深度复制。这样可能导致在析构函数释放的时候产生二次释放。
复制的时候要new新的内存,释放旧的内存,定义一个复制构造函数,重载赋值运算符。
c.delete和new不对应
使用new,就要在析构时候使用delete,使用new[],则在析构时候使用delete[]。
3.如果没有显式提供类方法,编译器将自动生成哪些类方法?请描述这些隐式生成函数的行为。
假如类名是ClassName:
ClassName(); 默认构造函数,如果没有构造函数的时候就会自动生成这个,里面不完成任何工作
ClassName(const ClassName&); 复制构造函数,浅复制
ClassName operator=(const ClassName&); 赋值函数,浅复制
~ClassName(); 析构函数,不做任何工作。
没有定义地址运算符,将提供地址运算符。返回对象地址,跟this指针的值一样。
4.找出并改正下述类声明中的错误:
class nifty
{
char personality[];
int talents;
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;
}
这个代码一堆错误,真的无语。几乎要重写的。
class nifty
{
private:
char personality[40];
int talents;
public:
nifty();
nifty(const char * s);
friend ostream & operator<<(ostream& os, const nifty& n);
};
nifty::nifty()
{
personality[0] = '\0';
talents = 0;
}
nifty::nifty(const char* s)
{
strcpy(personality, s);
talents = 0;
}
ostream & operator<<(ostream& os, const nifty& n)
{
os << n.personality << ":" << n.talents;
return os;
}
class Golfer
{
private:
char* fullname;
int games;
int * scores;
public:
Golfer();
Golfer(const char * name, int g = 0);
Golfer(const Golfer& g);
~Golfer();
};
Golfer nancy;//#1 Golfer()
Golfer lulu("Little Lulu");//#2 Golfer(const char* name, int g)
Golfer roy("Roy Hobbs", 12);//#3 Golfer(const char* name, int g)
Golfer * par = new Golfer;//#4 Golfer()
Golfer next = lulu;//#5 Golfer(const Golfer& g)
Golfer hazzard = "Weed Thwacker";//#6 Golfer(const char* name, int g)
*par = nancy;//#7 默认的赋值运算符
nancy = "Nancy Putter";//#8 Golfer(const char* name, int g),然后使用默认的赋值运算符
b.很明显,类需要有另外几个方法才能更有用,但是类需要哪些方法才能防止数据被损坏呢?
一个可以进行深度复制的赋值运算符。