在我的 C++ 编程课程中,我必须解决一个实际问题。 我的程序可以运行,但我不明白为什么。
任务的解决方法是正确执行main函数
int main()
{
STRING M1 = "Max";
STRING M2("Moritz");
STRING M3;
M3 = M1 + " und " + M2;
std::cout << "Wilhelm Busch:\n" << M3 << "\n";
M1 = "______________";
M1[0] = '+';
M1[M1.GetLength() - 1] = M1[0];
std::cout << M1 << '\n';
return 0;
}
并产生以下控制台输出:
Wilhelm Busch:
Max und Moritz
+------------+
我们创建了一个类
STRING
,它有几个构造函数:
class STRING
{
char *pBuf;
int Len;
public:
STRING() : pBuf(nullptr), Len(0){};
STRING(const char *pStr) : Len(strlen(pStr))
{
pBuf = new char[Len + 1];
strcpy(pBuf, pStr);
};
STRING(const STRING &other) : Len(other.Len)
{
pBuf = new char[Len + 1];
strcpy(pBuf, other.pBuf);
};
STRING(char C) : Len(6) //for testing purposes
{
for (int i = 0; i < 5; i++)
{
pBuf[i] = C;
}
pBuf[5] = '\0';
};
...
}
我们编写了一些像这样的运算符重载:
STRING &operator=(const STRING &other)
{
if (&other == this)
return *this;
delete[] pBuf;
this->Len = other.Len;
pBuf = new char[Len + 1];
strcpy(pBuf, other.pBuf);
return *this;
};
STRING operator+(const STRING &other)
{
char *temp = new char[other.Len + this->Len + 1];
strcpy(temp, this->pBuf);
strcat(temp, other.pBuf);
STRING newString(temp);
delete[] temp;
return newString;
};
现在在主函数中我不明白这行代码
M3 = M1 + " und " + M2;
令人惊讶的是,它确实工作正常,但我的运算符(
STRING operator+(const STRING &other)
)不支持来自数据类型char*
(即" und "
)的值,但仅支持来自对象STRING
的值。
我的代码中没有其他运算符operator+
。
当我尝试像这样重写同一行时:
M3 = M1 + 'D' + M2;
程序确实编译了,但没有给出任何输出,并在几秒钟后终止。 如果编译器使用相应的构造函数自动创建类
MaxDDDDDMoritz
的临时实例,我期望结果 STRING
。
(为了测试这一行,我添加了一个构造函数STRING(char C)
。)
对运算符重载的调用与对其他函数的调用完全相同。
特别是你的
STRING operator+(const STRING &other);
可以使用 STRING
参数调用overload。但是,
const
左值引用(即 const&
)不仅可以绑定到左值表达式,还可以绑定到右值表达式。这意味着它还可以绑定到类型为 STRING
的临时对象。
通常在 C++ 中,当调用函数时,总是会考虑对函数参数进行隐式转换,将其转换为目标类型。这就是为什么例如
void g(long);
也可以称为 g(1)
,尽管 1
的类型是 int
,而不是 long
。函数参数中的 int
对象是通过将 long
值 1
隐式转换为 int
来初始化的,在本例中,这会为 1
对象生成相同的值 int
。
隐式转换不仅发生在基本类型之间,还发生在用户定义类型之间,例如您的
STRING
。
特别是,对于这些所谓的用户定义的转换序列,除其他外,目标类的任何带有单个参数且未用关键字
explicit
标记的构造函数都可以考虑进行转换。
你有一个与此匹配的构造函数
STRING(const char *);
。它可用于将 const char*
转换为 STRING
。这个新的 STRING
对象是一个临时对象,一直存在到创建它的(完整)表达式的末尾,即 M3 = M1 + " und " + M2
的末尾,并且 operator+
的引用参数将绑定到这个临时对象STRING
对象,具有正确的引用类型。
因此重载是可行的,并且由于没有其他可行的重载,编译器将像这样使用它。
同样的情况也发生在
'D'
上,因为你有一个 STRING(char C);
构造函数。