运算符重载令人惊讶地有效,但我不明白为什么

问题描述 投票:0回答:1

在我的 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)
。)

c++ class constructor operator-overloading
1个回答
0
投票

对运算符重载的调用与对其他函数的调用完全相同。

特别是你的

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);
构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.