面试题1:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。
class CMyString
{
public:
CMyString(char *pData=NULL);//构造函数
CMyString(const CMyString& str);//拷贝构造函数
~CMyString();//析构函数
private:
char* m_pData;//数据域,字符指针
};
介绍重载赋值
【主要困惑的是,为什么定义函数的时候使用了&,下面重点讲解这个】
class CMyString
{
public:
CMyString(char *pData=NULL);//构造函数
CMyString(const CMyString& str);//拷贝构造函数
~CMyString();//析构函数
private:
char* m_pData;//数据域,字符指针
};
介绍重载赋值
【主要困惑的是,为什么定义函数的时候使用了&,下面重点讲解这个】
CMyString
&
operator=(const CMyString& str);
重载操作符是一些函数,其名字为关键字operator后紧跟需要重载的运算符,比如"operator="表示需要重载"="。像任何其他函数一样,操作符函数有一个返回值和一个形参表。形参表必须具有与该操作符操作数数目相同的形参,但是如果操作符是一个成员函数,它的第一个操作数隐式绑定到this指针,因此形参表中的参数会减少一个。因为赋值运算符必须是类的成员函数,所以this绑定到左操作数的指针。因此,赋值操作符只接受一个形参,且该形参是同一类型的对象,右操作数一般作为const引用传递,跟拷贝构造函数相同。
赋值操作符的返回类型应该与内置类型赋值运算的返回类型相同,内置类型的赋值运算返回对左操作数的引用,因此赋值操作符也返回对同一类类型的引用。赋值必须返回对*this的引用,也就是左操作数的引用。 一般而言,赋值操作符与复合赋值操作符应返回左操作数的引用。
重载操作符是一些函数,其名字为关键字operator后紧跟需要重载的运算符,比如"operator="表示需要重载"="。像任何其他函数一样,操作符函数有一个返回值和一个形参表。形参表必须具有与该操作符操作数数目相同的形参,但是如果操作符是一个成员函数,它的第一个操作数隐式绑定到this指针,因此形参表中的参数会减少一个。因为赋值运算符必须是类的成员函数,所以this绑定到左操作数的指针。因此,赋值操作符只接受一个形参,且该形参是同一类型的对象,右操作数一般作为const引用传递,跟拷贝构造函数相同。
赋值操作符的返回类型应该与内置类型赋值运算的返回类型相同,内置类型的赋值运算返回对左操作数的引用,因此赋值操作符也返回对同一类类型的引用。赋值必须返回对*this的引用,也就是左操作数的引用。 一般而言,赋值操作符与复合赋值操作符应返回左操作数的引用。
其中:
this是指向本类的指针,*this就是this所指向的对象,即当前对象;另外补充一点,(*this).data与this->data是等价的。
&
从上述基础知识我们知道了重载赋值操作符是一个类的成员函数,这个函数的返回类型是左操作数的引用,也就是*this,并且这个函数的参数是一个同类型的常引用变量。通过上述知识我们可以确定重载操作符函数为:
CMyString& operator=(const CMyString& str);//重载运算符
CMyString& operator=(const CMyString& str);//重载运算符
完整的代码实现如下:
第一种解法:
#include "stdafx.h"
#include<iostream>
#include<stdlib.h>
using namespace std;
void CMyString::Print()
{
cout << m_pData << endl;
}
//构造函数
CMyString::CMyString(char *pData)
{
if (pData == nullptr) //如果构造函数的参数为空
{
m_pData = new char[1];
m_pData[0] = '\0'; //初始化字符串,内容为'\0'
}
else //如果构造函数的参数不为NULL,那么首先求出字符串长度,然后new一个长度为len+1的字符数组
{
int len = strlen(pData);
m_pData = new char[len + 1];
strcpy_s(m_pData, len+1, pData);//字符串拷贝
}
}
//析构函数
CMyString::~CMyString()
{
delete[] m_pData;
}
//拷贝构造函数,拷贝构造函数与构造函数的思路非常类似。
CMyString::CMyString(const CMyString& str)
{
int len = strlen(str.m_pData);
m_pData = new char[len + 1];
strcpy_s(m_pData, len+1,str.m_pData);
}
//重载运算符
CMyString& CMyString::operator=(const CMyString& str)
{
//如果传入的参数与当前的实例是同一个实例,则直接返回自身
if (this == &str)
return *this;
//释放实例自身已有内存
delete[] m_pData;
m_pData = nullptr;
//在删除自身内存以后在重新new一个长度为len+1的字符数组,类似拷贝构造函数
int len = strlen(str.m_pData);
m_pData = new char[len + 1];
strcpy_s(m_pData,len+1, str.m_pData);
}
char* strs = "hello";
CMyString str1(strs);//调用了构造函数
CMyString str2;
CMyString str3(str1);//调用了拷贝构造函数
CMyString str4=str1;//调用了拷贝构造函数
str2 = str1;//调用了赋值运算符函数
str1.Print();
str2.Print();
str3.Print();
str4.Print();
system("pause");
第二种解法
CMyString& CMyString::operator=(const CMyString& str)
{
if (this != &str)//
{
CMyString strTemp(str); //使用构造函数创建一个临时对象
//交换临时对象与当前对象的m_pData值
char* pTemp = strTemp.m_pData;
strTemp.m_pData = m_pData;
m_pData = pTemp;
}
return *this;
}
注意:在编写代码的过程中,遇到了这种错误:
错误
2
error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
d:\program files\microsoft visual studio\vc\include\sal.h
2381
1
1_CMyStringOp
错误
1
error C2144: 语法错误:“int”的前面应有“;”
d:\program files\microsoft visual studio\vc\include\sal.h
2381
1
1_CMyStringOp
原因:在文件头部多写了一个中文格式的':