--又是一度c++填坑小日常,讲真,真为自己的智商作急。这一篇也有讲到所谓的空指针的坑。本人才疏学浅,希望有错的地方能指出来。
1.先给概念:什么是拷贝构造函数?(关于这个随手就能百度出来的答案,大家看看就好)
拷贝构造函数,又称复制构造函数,是一种特殊的构造函数。算了,直接来个连接吧:百度连接。
2.实现的要求:将下列实现类外要求;
class Employee{
char * name; // 姓名
char * post; // 职务
public:
// 构造函数,职务可以为空,姓名不能为空
Employee(char * s1, char * s2 = NULL);
// 拷贝构造函数
Employee(const Employee & other);
vod setPost(char * str);
char * getName() const {return name;}
char * getPost() const {return post;}
// 析构函数
~Employee() {delete [] name; delete [] post;}
};
Employee(char*s1,char*s2=NULL)这段代码是坑!是坑!什么叫报错无极限还弄死都找不到。就是char*s2=NULL闹得鬼!!!
char*s2=NULL,中的s2是空指针,这里的空指针不等于空字符串。空字符串的正确表达方式是;Cchar+s2=""。空字符串里面至少还有结束字符.
空指针是特殊的指针,由于这个指针不指向任何地方,这就意味任何一个有效的指针和空指针进行相等的比较运算时妥妥的报错。
// 构造函数,职务可以为空,姓名不能为空 这一句的理解是,所说的内容为空,并不是空指针。
关于这个现象怎么处理,加入特判。关键是在哪里加,为什么要在那里加。我加的地方 setPost函数那里。先见源代码在慢慢说事。
3.一言不合放代码:
类外实现加主函数
#include<iostream>
#include<string>
#include<string.h>
using namespace std;
class Employee
{
char *name;
char *post;
public:
Employee(char *s1, char *s2 = NULL);
Employee(const Employee &other);
void setName(char *str);
void setPost(char *str);
char *getName() const{return name;}
char *getPost() const{return post;}
~Employee() { delete[] name; name = NULL; delete[] post; post = NULL; }
};
Employee::Employee(char *s1, char *s2)
{
setName(s1);
setPost(s2);
}
Employee::Employee(const Employee &other)
{
name = new char[strlen(other.getName()) + 1];
strcpy(name, other.getName());
post = new char[strlen(other.getPost()) + 1];
strcpy(post, other.getPost());
}
void Employee::setName(char *str)
{
name = new char[strlen(str) + 1];
strcpy(name, str);
}
void Employee::setPost(char *str)
{
if (str == NULL)
{
post = new char[1]; //仅仅是这一点我找了三天, strlen()里面不能为空,这就算啦。
strcpy(post, "");//空指针不能随便赋值,
//我之前就是没有给空指针给予空间,虽然这个空间依然是表达为空
}
else
{
post = new char[strlen(str) + 1];
strcpy(post, str);
}
}
void printEmployee(const Employee & e)
{
cout << "The employee's name: " << e.getName() << endl;
cout << "The employee's post: " << e.getPost() << endl;
cout << endl;
}
int main()
{
Employee a("张三", "工程师");
Employee b("李四");
Employee c = a;
printEmployee(a);
printEmployee(b);
printEmployee(c);
system("pause");
return 0;
}
加了蓝色的就是关于空指针需要特判的地方,也是需要注意的地方。
~Employee() { delete[] name; name = NULL; delete[] post; post = NULL; }
空指针指向的内存区域为内存的首地址,是不可读写的区域,即空指针不提供操作。删除空指针是安全的(因为它什么也没做)。所以,在写构造函数,赋值操作符,或其他成员函数时,类的每个指针成员要么指向有效的内存,要么就指向空,那在你的析构函数里就可以delete 掉空指针。(简单的说c++可以delete空指针,但是c++不能delete野指针)。
在delete后面加上name=NULL的理由是:delete是释放指针指向的内存,而不是指针本身所占的内存。所以delete后,指针还是指向原来的那块区域,并未清零,所以如果下次用到就会发生,就会说XXX空间不能访问。(打个比喻,就是你开车回家,印象中那条回家的路应该是有你的老房的,结果拆迁成了花园,你就看不到你的老家了。)所以一定要记着,免得徒增伤感。
(2)在蓝色的Employee::Employee(char *s1, char *s2)中:
由于要实现Employee b("李四");时候:由于没有输入职业,然后在类的定义时将post定义成了空指针,然而在重新根据原来的大小开出一个字符串空间来的时候,要用到strlen,而strlen的参数只能是char* 且必须是以'\0'结尾的,为什么strlen参数是这样就要翻strlen实现的源码了。