【问题标题】:Operator = Overload with Const Variable in C++运算符 = 用 C++ 中的常量变量重载
【发布时间】:2010-10-19 01:23:07
【问题描述】:

我想知道你们是否可以帮助我。

这是我的 .h:

Class Doctor {
   const string name;
   public:
       Doctor();
       Doctor(string name);
       Doctor & Doctor::operator=(const Doctor &doc);
}

和我的主要:

int main(){
    Doctor d1 = Doctor("peter");
    Doctor d2 = Doctor();
    d2 = d1;
}

我想做 operator= 函数。谁能帮我?注意 Doctor 上的 const 成员。

************编辑:********* 我的主要问题是我希望另一个类有一个属性,它是一个医生,就像一个病人有一个医生。但我希望能够改变我的医生。就像我正在看医生 A 但我想看医生 B。这将在我的其他班级 (Pacient) 中使用 setDoctor 函数来完成。如果是我编写代码,我会这样说:

class Patient{
    Doctor &d;
};

然后更改指针。但是,我使用的是一位老师制作的基本代码,它的类定义如下:

class Patient{
     Doctor d;
}

但我认为这是不可能的,因为在 Patient 类中使用 setDoctor() 时,我要么制作副本,要么更改变量本身。第一个没有任何区别,第二个由于 const 是不可能的。我说的对吗?

【问题讨论】:

  • 如果它明显要改变,你为什么要把它设为 const?
  • 但是它没有初始化……我记不太清楚了,但我认为它一旦初始化就不能改变。
  • 你不是复制构造函数有什么原因吗?
  • 但是他在做 d2 = d1 - 这意味着 d2 的名字应该改变。
  • 您所要求的无法完成。按定义分配会更改您分配给的对象。如果它是 const,你就不能这样做。如果 'name' 字符串是 const,那么它一旦被初始化就不能被修改。如果你做一个赋值运算符,它必须跳过'name'字符串。

标签: c++ operators operator-overloading constants conversion-operator


【解决方案1】:

您还想将返回类型更改为 const&:

const Doctor& operator=(const Doctor &doc);

省略 const 将使以下代码可编译,而实际上它们是无效的:

(A = B) = C;

等同于以下内容:(这可能是预期的)

A = B = C;

【讨论】:

    【解决方案2】:

    正确定义赋值构造函数使其异常安全的标准方法是根据复制构造函数来定义它。

    class Doctor
    {
        public:
            Doctor& operator=(Doctor const& rhs)
            {
                if (this != &rhs)
                {
                    Doctor  tmp(rhs);  // Use copy constructor here
                    this->swap(tmp);   // Now Swap
                }
                return *this;
            }
            void swap(Doctor& rhs) throws()
            {
                std::swap(.....); // swap each member variable.
            }
    };
    

    通过这样做可以使其异常安全。
    请注意,您只需要将交换设置为无抛出方法,如果您使用 STL 对象,这相对简单,因为它们都为这种情况定义了无抛出交换,boost 和所有好的库也是如此(因此您应该遵循套件)。

    如果这出错了,他们在使用复制构造函数时就会出错。此时,您尚未修改自己的对象,因为您正在将构造复制到临时对象中。因此,您提供了良好的异常安全性,因为您的对象仍未更改。

    【讨论】:

      【解决方案3】:

      你快到了。几个值得注意的点:

      • 名称不应为const 限定。 const 不能修改,这正是我们在赋值运算符中想要的。

      • C++ 关键字是 class 而不是 Class,因为你的代码有它(它会给你编译错误)

      • 正如 Michael Burr 所指出的:“应该注意的是,如果该类仅包含其他已经正确支持赋值的类(如在本例中使用简单的字符串成员),则编译器生成的隐式运算符 = () 会工作得很好。”在这里,就您而言,唯一的成员 string 具有正确的 op=。所以明确定义是多余的。

      • Meeh 的解决方案就差不多了。它唯一没有谈论的是自我分配。阅读FAQ 12

      • 赋值是三大成员函数FAQ 27.10 之一。查一下。它说,实现 copy ctor、op= 或 dtor 之一的要求通常意味着您还需要实现其他两个。

      更正后的代码示例应该是这样的:

      class Doctor {
        string name;
        public:
          Doctor& operator=(Doctor const& o) { 
               if (&o != this) name = o.name;
               return *this;
          }
        // ...
      };
      

      【讨论】:

      • 应该注意的是,如果该类仅包含已经正确支持赋值的其他类(如在本例中使用简单的字符串成员),则隐式的、编译器生成的 operator=() 将起作用很好。
      • @Michael:是的,我应该添加这个。我会编辑我的帖子。
      • @Michael:如果我们有“Doctor d1 = NULL; Doctor d2 = Doctor(); d1 = d2;”,const 问题也同样适用?
      【解决方案4】:

      正如许多人之前所说,成员是 'const' 表示它必须在创建期间进行初始化,并且不应更改。 如果你必须为这种情况编写一个赋值运算符并且你不能跳过该成员变量的赋值,那么将其设为“可变”。

      记住;从 C++ 标准来看,“抛弃最初声明的 const 变量的 const 是未定义的行为。”

      HTH, 阿拜

      【讨论】:

        【解决方案5】:

        既然你的名字是 const,那么“改变”它的唯一方法就是通过构造函数。如果你想使用 = 操作符,你需要“unconst”这个字符串。

        .. 如果你不想“unconst”字符串,你可以通过创建一个复制构造函数来获得一些相同的行为:

        Doctor(const &Doctor d);
        

        .. 并实施它:

        Doctor::Doctor(const &Doctor d)
           : name(d.name)
        {
        //Im pretty sure you have access to private attributes here
        // My C+ is a bit rusty :) If not, make a const string getName() method
        }
        

        【讨论】:

        • 你必须在初始化列表中初始化字符串,而不是在构造函数体内: Doctor::Doctor( const Doctor& d ) : name( d.name ) {}
        • 要添加到dribeas的更正中,您也不能在构造函数中更改字符串。字符串是常量。唯一可以改变字符串的是字符串的构造函数本身。
        【解决方案6】:

        声明为Doctor &operator=(const Doctor &other);(即删除Doctor::)

        从那里你需要使用 const_cast 来删除成员变量的 const-ness 以使其工作。请注意,只有心碎在于您选择的道路。

        我建议从成员声明中删除 const,并根据需要使成员函数 const 以表明它们不会影响对象。 (例如,如果你有一个访问器成员函数,你可以声明 const: string getName() const { return m_name; }

        【讨论】:

        • 确实.. const_cast 是魔鬼制造的 :) 这就是为什么我没有将它添加到我的答案中。
        猜你喜欢
        • 2013-10-14
        • 1970-01-01
        • 2013-11-10
        • 1970-01-01
        • 1970-01-01
        • 2018-12-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多