当我重载动态字符串类的运算符时没有匹配的构造函数
No matching constructor when I overload operator for dynamic string class
我的字符串类有问题。
构造函数和复制构造函数:
private:
char * buf;
public:
String( const char * s = "")
{
buf = strdup(s);
}
String( String &s)
: buf(strdup(s.buf))
{
}
操作员:
String operator + ( const String &s )
{
char* tmp = new char[strlen(buf) + strlen(s.buf) + 1]; // +1 for the terminating ' '
strcpy(tmp,buf);
strcat(tmp,s.buf);
String result;
delete[] result.buf;
result.buf = tmp;
return result;
}
String operator += ( const String s )
{
delete_char_array(buf);
char* tmp = new char[strlen(buf) + strlen(s.buf) + 1];
strcpy(tmp,buf);
strcat(tmp,s.buf);
buf = strdup(tmp);
delete_char_array(tmp);
return *this;
}
void print( ostream & out )
{
char *p = buf;
out << p;
}
我已经实现了<<运算符
ostream & operator << ( ostream & out, String str )
{
str.print(out);
return out;
}
我的 main(( 函数是:
int main()
{
String firstString("First");
String secondString("Second");
cout << firstString + secondString << endl;
(firstString+=secondString).print(cout);
}
我可以通过 String.print(cout( 正确获取输出,但 g++ 会告诉我
cout << firstString + secondString << endl;` does not have the matching
constructor for `String::String(String)`
有两种选择,1. String::String( char * c)
和 2. String::String(String &s)
.
这应该是复制构造函数签名:
String(String const& s)
因此,引用可以绑定到 operator+
返回的 R 值。此外,您还应该将此签名用于operator<<
:
ostream &operator<<(ostream &out, String const& str)
这些片段中的任何一个都可以修复错误,但是 (1( 是至关重要的做法(如您所见(,(2( 避免复制。
你还需要做void print(ostream &out) const
,因为你想用String const&
来称呼它,即使operator+
也应该const
。请不要忘记const
...
您不修改引用 - 使其成为对常量的引用。成员函数不会修改*this
- 使其const
。就是这么简单。
你在这里也忘记了一个&
:String operator+=(const String s)
.
我们还没有完成,正如PaulMcKenzie的评论所指出的那样,还有很多事情需要解决。
你的String
类有一些问题。
首先,strdup
的使用返回应使用 free()
解除分配的已分配缓冲区。 但是,在重载的+=
和+
函数中,您使用的是new []
和delete []
。 您正在使用C++,因此请假装 strdup(( 不存在。
尽管您试图小心它,但像这样混合分配函数是未定义的行为。 相反,请在整个类代码中使用new []
和delete []
。
其次,复制构造函数签名应为:
String(const String &s);
所以你的构造函数现在应该看起来像这样:
private:
char * buf;
public:
String( const char* s = "") : buf(new char[strlen(s) + 1]())
{
strcpy(buf, s);
}
String(const String &s) : buf(new char[strlen(s.buf) + 1]())
{
strcpy(buf, s.buf);
}
现在需要添加析构函数(如果尚未添加
(:String::~String() { delete [] buf; }
接下来是你的operator +=
和operator +
. operator +=
应该返回对当前对象的引用,而不是全新的对象。
String& operator += ( const String& s )
{
char* tmp = new char[strlen(buf) + strlen(s.buf) + 1];
strcpy(tmp,buf);
strcat(tmp,s.buf);
delete [] buf;
buf = tmp;
return *this;
}
请注意,返回类型是对 String
的引用。 另请注意,在尝试删除旧缓冲区之前,首先分配串联字符串的内存。 需要这样做以确保缓冲区在引发异常时不会operator new
失效。
鉴于此,operator +
可以这样写:
String operator + ( const String& s )
{
String tmp(*this);
return tmp += s;
}
我们使用operator +=
作为辅助函数。 所做的只是创建一个与*this
相同的临时String
。 然后我们只需返回传入的String
operator +=
的结果。 简短而简单。
您缺少的最后一件事是赋值运算符。如果没有赋值运算符,则无法安全地执行以下操作:
String s1("abc");
String s2;
s2 = s1; // <-- assignment operator here
实现赋值运算符非常容易,前提是您有一个复制构造函数和工作析构函数。 请转到此链接了解如何实现此功能:
复制/交换成语。
- 构造函数和转换运算符之间的重载解析
- 复制构造函数、赋值运算符C++
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- 为什么我的运算符 + 重载尽管是通过引用传递的,但仍调用我的复制构造函数?
- 让某个类的 '=' 运算符在声明时运行构造函数
- C++:使用运算符 = 调用多参数构造函数
- 应用于运算符而不是构造函数的显式关键字
- 运算符+ 的规范实现涉及额外的移动构造函数
- 运算符 new 的执行顺序和构造函数的参数
- 非模板 std::reference_wrapper赋值运算符和模板构造函数
- 如果我也使用复制构造函数并且重载 = 运算符,我是否需要析构函数?
- 复制构造函数和赋值运算符的值类实现
- 在构造函数中使用重载运算符?
- 在C++中,我可以在定义自己的复制构造函数后跳过定义赋值运算符吗?
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- C++ 类的构造函数和函数调用运算符 () 重载之间的歧义
- 删除了所有自动生成的构造函数/运算符的类仍然可以从函数返回吗
- 为简单结构定义哪个复制/移动构造函数/运算符