复制构造函数,赋值运算符重载

时间:2014-08-19 06:24:08

标签: c++ object instance copy-constructor assignment-operator

单位现在我从不需要重载赋值参数或编写复制构造函数 (至少,我似乎没有必要,因为我从未遇到过问题)

据我所知,当我想在初始化后将Object及其值复制到另一个Object时,必须重载赋值运算符(与CopyConstructor相同,但初始化时)。

Object a;
Object b;

// do something with a
b = a; //for this line, the Assignment Parameter must be overloaded (nearly never do such things)
Object c = a; // needs a Copy constructor 

但如果我这样写的话:

Object a;
Object* b;

b = &a; //I think I won't need one here since b actually points to Object a
Object* c = a; // I think same here

但是,如果我将一个对象复制到自己的类/父类之外,我应该怎么做。

class MyOtherClass{Object obj..........}

void MyOtherClass::SetObject(Object obj)
{
  this->obj = obj; // Assignment operator overloading needed in class Object?
}

我是否必须重载Object类中的赋值运算符? 如果我这样做会怎么样:

void MyOtherClass::SetObject(Object &obj)
{
  this->obj = obj; // Assignment operator overloading needed in class Object?
}

最后一个问题,这还包括Enums吗?(我想是的)

void MyOtherClass::SetObject(ENumClass Eobj)
.
.

3 个答案:

答案 0 :(得分:1)

关于是否实现赋值运算符的问题,答案是 - 它取决于。

请记住,如果您自己不提供默认赋值运算符,编译器将生成它自己的默认赋值运算符(如果您没有明确禁用默认运算符,则在C ++ 11中)。默认运算符使用自己的赋值运算符执行每个类成员的赋值。

因此,只要您的类成员本身具有赋值安全性,那么默认运算符就足够了,您无需提供自己的运算符。您只需在需要执行自定义操作时提供自己的操作符,例如深度复制动态分配的成员,调试日志记录,输入验证等。

答案 1 :(得分:0)

编写从基类型赋值的赋值运算符是合法的,编写从同一类型的具体对象赋值的赋值运算符也是合法的。然而,即使两者都是合法的,通常更好的设计是从相同类型的对象实现赋值,或者从其他具体类型实现赋值,而这些赋值实际上是有意义的,而不是来自一般类型。

话虽如此,但从应用程序到应用程序确实有所不同。更具体一点,请考虑:

                     Shape
        /             |                \
      Triangle      Quadrilateral      Circle

...在Circle中有一个可以从任何Shape赋值的赋值运算符可能没有意义。这种方法甚至会做什么?这些不同的实现没有任何共同之处。

现在,或者,考虑:

                     Point2D
                     /     \
          CartesianCoord   PolarCoord

...在这样的应用程序中,提供一个接受一般Point2D的赋值运算符以便于两种类型之间的转换可能是有意义的。在这种情况下,所有实现都表示相同的信息,并且可以在表示之间非破坏性地转换。因此,在这种情况下,允许更一般的转换是有意义的。

所以,真的,这完全取决于概念上有意义的东西。如果您可以以不破坏信息的方式分配给对象/从对象分配,那么它是理智的;如果你的任务是破坏性的,那么它很可能是一个糟糕的设计。

至于参数,通常使用" const T&" (其中" T"是您指定的类型)或" T&&"在破坏性分配的情况下。赋值的返回类型应该是对与当前对象相同类型的对象的引用。换句话说:

class CartesianCoord : public Point2D {
 public:
   // ...
   CartesianCoord& operator=(const Point2D&);
};

或者

class CartesianCoord : public Point2D {
 public:
   // ...
   CartesianCoord& operator=(const Point2D&);
   CartesianCoord& operator=(CartesianCoord&&); // fast destructive assignment
};

或者

class CartesianCoord : public Point2D {
 public:
   // ...
   CartesianCoord& operator=(const CartesianCoord&);  // if conversion disallowed
   CartesianCoord& operator=(CartesianCoord&&); // fast destructive assignment
};

答案 2 :(得分:0)

为什么使用单独的方法SetObject()复制operator =()语义?

因此,正确地将基类分配给派生,您可以通过这种方式在派生对象中重载operator =()

DerivedObj& DerivedObj::operator=(const BaseObj& rhs){
    // call parent operator= in functional form
    BaseObj::operator=(rhs);
    return *this;
}

当然你应该实现

BaseObj& BaseObj::operator=(const BaseObj& rhs)

但是如果你需要为派生分配基类,我不会说这是一个好的设计