我正在尝试编写自己的C ++ String类,用于教育和需求目的 首先,我对操作员知之甚少,这就是我想学习它们的原因。 我开始写我的课程但是当我运行它时它会阻止程序,但不会造成任何崩溃 在进一步阅读之前,请先查看以下代码:
class CString
{
private:
char* cstr;
public:
CString();
CString(char* str);
CString(CString& str);
~CString();
operator char*();
operator const char*();
CString operator+(const CString& q)const;
CString operator=(const CString& q);
};
首先,我不太确定我宣布一切正确。我尝试谷歌搜索它,但所有关于重载的教程解释了基本的ideea,这很简单,但缺乏解释如何以及何时调用每个东西。例如,在my =运算符中,程序调用CString(CString& str);但我不知道为什么。
我还附上了下面的cpp文件:
CString::CString()
{
cstr=0;
}
CString::CString(char *str)
{
cstr=new char[strlen(str)];
strcpy(cstr,str);
}
CString::CString(CString& q)
{
if(this==&q)
return;
cstr = new char[strlen(q.cstr)+1];
strcpy(cstr,q.cstr);
}
CString::~CString()
{
if(cstr)
delete[] cstr;
}
CString::operator char*()
{
return cstr;
}
CString::operator const char* ()
{
return cstr;
}
CString CString::operator +(const CString &q) const
{
CString s;
s.cstr = new char[strlen(cstr)+strlen(q.cstr)+1];
strcpy(s.cstr,cstr);
strcat(s.cstr,q.cstr);
return s;
}
CString CString::operator =(const CString &q)
{
if(this!=&q)
{
if(cstr)
delete[] cstr;
cstr = new char[strlen(q.cstr)+1];
strcpy(cstr,q.cstr);
}
return *this;
}
为了测试,我使用的代码就像这一样简单
CString a = CString(“Hello”)+ CString(“World”);
的printf(一);
我试过调试它,但在某一点上我迷路了。首先,它为“hello”和“world”调用构造函数2次。然后它在+运算符中就可以了。然后它调用空字符串的构造函数。之后它进入“CString(CString& str)”,现在我迷路了。为什么会这样?在此之后我注意到我的包含“Hello World”的字符串在析构函数中(连续几次)。我又一次非常困惑。再次从char *转换为Cstring后来回停止。它永远不会进入=运算符,但它也不会进一步发展。从未到达printf(a)
我使用VisualStudio 2010,但它基本上只是标准的c ++代码,因此我认为它不应该产生那么大的差异
答案 0 :(得分:4)
该行:
cstr=new char[strlen(str)];
应该是:
cstr=new char[strlen(str) + 1];
此外,自我赋值测试在复制构造函数中没有意义 - 您正在创建一个新对象 - 它不可能与任何现有对象具有相同的地址。复制构造函数应该将const引用作为参数
如果在您的代码中,您希望使用赋值运算符,那么您可能会遇到错误。这段代码:
CString a = CString("Hello") + CString(" World");
基本上与:
相同CString a( CString("Hello") + CString(" World") );
这是复制构造,而不是分配。在构造之后,临时CString“Hello world”将被销毁(调用析构函数)。
基本上,听起来好像你的代码正在按预期工作或多或少。
答案 1 :(得分:3)
不要使用strlen,存储自己的字符串长度。不应该依赖该字符串来使用null终止符。如果你传入一个随机的const char *,可以使用它,但对于内部操作,你应该使用这个大小。
另外,你忘了让你的操作符const char *一个const重载。
答案 2 :(得分:1)
这是发生了什么:
CString a = [CString result of operator +]
,c ++只会称你为复制构造函数。因此,您在调试器中看到的CString(CString& )
调用。现在,刚刚创建了4个对象,每个字符串文字对应一个(“hello”和“world”),一个用于串联(CString::operator +
调用的结果,一个用于保存)结果(CString a = ...
)。每个临时对象都会调用它的析构函数。
至于为什么你没有得到printf,我不知道。我只是将您的代码复制粘贴到此文件中:
#include <cstdio>
#include <cstring>
[your code]
int main(int argc,char* argv[]) {
CString a = CString("hello") + CString(" world");
printf(a);
}
当我运行生成的可执行文件时,我得到hello world
作为输出。这是在Ubuntu上使用g ++ 4.4。不完全确定为什么在VS调试器下它没有打印任何东西。
答案 3 :(得分:0)
你犯了一些错误:
1。复制构造函数签名是错误的。必须是:
CString(const CString& q)
2。 op =签名是错误的。必须是:
CString& operator=(const CString& q)
顺便说一下,这也是调用复制构造函数的原因。你最后做了一个return *this
复制了对象(用你的op =签名)。
3。您允许CString实例使用cstr == NULL
(您的默认构造函数将导致此类实例)。但是,在几乎所有函数(复制构造函数,operator +
,operator =
)中,您都没有很好地处理这种情况(q.cstr == NULL
)。
也许最简单,最安全的方法就是不允许这种情况并将默认构造函数更改为:
CString::CString()
{
cstr = new char[1];
cstr[0] = 0;
}