【问题标题】:Assignment = operator overloading赋值 = 运算符重载
【发布时间】:2012-04-28 21:18:07
【问题描述】:

请帮忙完成这个赋值重载函数的执行。

说明如下:

赋值运算符 (=) 将源字符串复制到目标字符串中。请注意,目标的大小需要调整为与源的大小相同。

加法 (+) 和赋值 (=) 运算符都需要能够进行级联运算。这意味着 String3 = String1 + String2String1 = String2 = String3 应该可以工作。

这是我的 .cpp 文件:

 int MyString::Length()
 {
       int counter(0);

       while(String[counter] != '\0')
       {
            counter ++;
       }
     return (counter);
 }

MyString& MyString::operator=(const MyString& rhs)
{

        if(this != &rhs)
        {

                delete [] String;
                String = new char[rhs.Length()];

             for(int i = 0; i <rhs.Length()+1 ; i++)
            {       
                  String[i] = rhs.String[i];
            }       


        }
        return *this;

}

在main.cpp文件中被调用:

String1=String2=String3;

我觉得我好像错过了什么。求助!!

【问题讨论】:

  • 在异常面前思考正确性!
  • 具体是什么问题?
  • 您正在保留this-&gt;Size 字符,您正在复制this-&gt;counter 字符。不应该是rhs.Size 还是rhs.counter
  • 你也忘了更新那些变量
  • 你有 4 个问题,本质上问的是同一件事。

标签: c++ operator-overloading cascade assignment-operator


【解决方案1】:

查看copy and swap idiom

您的代码的一个问题是它不是异常安全的。
它甚至不符合basic exception guarantee

如果它在新操作期间抛出,您的对象将处于完全无法使用的状态。如果事实处于危险状态,因为如果由于异常而在堆栈展开期间调用析构函数,则会出现未定义的行为,因为析构函数将在 String 上第二次调用 delete。

对象上的所有方法都应该分三个阶段起作用:

  1. 在不改变对象的情况下做所有可以抛出的工作。
    • 因此,如果您确实抛出该对象,则该对象仍处于良好状态。
  2. 以异常安全的方式将您在 (1) 中创建的数据与对象数据交换。
    • 这就是为什么swap() 方法是无抛出的
  3. 整理并删除。
    • 可以抛出,因为对象再次处于一致状态。

复制和交换习语将这些步骤很好地封装在一种易于使用的技术中。

【讨论】:

  • 不需要进行“整理和删除”,因为在 C++ 中我们使用的是智能指针。 (你是,对吧?)
  • @MooingDuck:智能指针是一种实现技术。原则仍然存在,有一个整理和阶段。此外,String 实际上是一个容器,因此智能指针并不真正适用。智能指针和容器是应用于内存管理的不同但并行的技术。
【解决方案2】:

我想Stringchar*。或许那时,Size,也就是新的长度,需要设置为 rhs 的长度,也就是新的字符串。所以应该是rhs.Size,而不是this->Size,很可能是这样。请注意,在 char 数组大小中也应考虑终止空字符。

之后您可以进入循环,再次处理所有字符和终止空字符。鉴于我们不知道 counter 是什么,并假设它是没有空字符的新字符串长度(因此,+ 1 占了它),我想循环没有任何问题。

【讨论】:

  • 所以当我说 String = new char[Size.Length()] 这就是你的意思吗?还是应该这样声明,Size = rhs.Size;是的,我在循环中搞砸了,但我已经编辑了它。
  • 在'delete [] String'之后,应该这样做:'Size = rhs.Size'。完成之后,新的“String”应该是:“String = new char[rhs.Size]”,或者只是“String = new char[Size]”,因为“Size”现在等于“rhs.Size” .如果 Size 忽略终止字符,则添加一个。这里的重点是您需要使任何成员变量等于作为参数传递给赋值运算符的对象。
  • 很高兴知道你做错了什么。但最后你必须使用复制和交换(或弄清楚如何以异常安全的方式编写它)。复制和交换的习语也只有三行,知道了以后写起来也比较容易。
  • 感谢您的帮助!我想通了! :)
【解决方案3】:

在开始赋值运算符重载之前,让我们看一下 C++ 中的运算符重载。在面向对象的编程中,运算符重载(不太常见的称为 operator ad hoc 多态性)是多态性的一种特殊情况,不同的运算符根据其参数有不同的实现。运算符重载通常由语言、程序员或两者定义。使用运算符重载是因为它允许开发人员使用更接近目标域的符号进行编程,并允许用户定义的类型与语言中内置的类型具有相似级别的句法支持。例如,在科学计算中很常见,它允许使用与纸上相同的语法来操作数学对象的计算表示。可以使用函数调用来模拟对象重载。

现在我们如何重载赋值运算符 (=),

在我们完成这个赋值运算符重载之后,我们将能够为我们自定义数据类型的两个变量赋值。让我们看看下面的例子:

// Operator overloading in C++
//assignment operator overloading
#include<iostream>
using namespace std;

class Employee
{
private:
int idNum;
double salary;
public:
Employee ( ) {
    idNum = 0, salary = 0.0;
}

void setValues (int a, int b);
void operator= (Employee &emp );

};

void Employee::setValues ( int idN , int sal )
{

salary = sal; idNum = idN;

}

void Employee::operator = (Employee &emp)  // Assignment operator overloading function
{
salary = emp.salary;
}

int main ( )
{

Employee emp1;
emp1.setValues(10,33);
Employee emp2;
emp2 = emp1;        // emp2 is calling object using assignment operator

}

现在让我们解释重载“=”运算符的代码,我们使用函数“setValues”将值分配给“idN”和“sal”,该函数是“Employee”类的公共成员函数,现在我们的主要point 是定义为“operator =”的重载函数。在这个函数中,我们将薪水的值赋值给同一个类的另一个变量,这样我们就可以直接在我们的 main() 函数中使用赋值运算符。现在你可以在main()中看到,我们有两个Employee类型的变量emp1和emp2,我们可以在最后一行代码中直接使用赋值运算符,这都是因为赋值运算符重载或运算符“=”的运算符重载”。

【讨论】:

    猜你喜欢
    • 2013-03-30
    • 2013-02-14
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-13
    • 2011-03-06
    • 2018-12-27
    • 1970-01-01
    相关资源
    最近更新 更多