C++ 对这两个赋值运算符的不同感到困惑吗

C++ 对这两个赋值运算符的不同感到困惑吗,c++,C++,我有一个叫做CoordinatesList的类。它包含一个坐标的动态数组,其中每个坐标有3个整数;x、 y和z。 在类Coordinates列表中,我有两个不同的成员运算符=,我对它们之间的区别有点困惑 如果我继承了类coordinates列表中的类坐标,它会起同样的作用吗 class Coordinates {//this is a complete class, do not modify it. public: Coordinates() { x = new int

我有一个叫做CoordinatesList的类。它包含一个坐标的动态数组,其中每个坐标有3个整数;x、 y和z。 在类Coordinates列表中,我有两个不同的成员运算符=,我对它们之间的区别有点困惑

如果我继承了类coordinates列表中的类坐标,它会起同样的作用吗

class Coordinates {//this is a complete class, do not modify it.
public:
    Coordinates() {
        x = new int; y = new int; z = new int;
        *x = *z = *y = 0;
    }
    Coordinates(int _x, int _y, int _z) {
        x = new int; y = new int; z = new int;
        *x = _x;
        *z = _y;
        *y = _z;
    }
    Coordinates(const Coordinates& rhs) { // copy constructor
        x = new int; y = new int; z = new int;
        *x = *(rhs.x);
        *y = *(rhs.y);
        *z = *(rhs.z);
    }
    ~Coordinates() {
        delete x; delete y; delete z;
    }
    void operator=(const Coordinates& rhs) {//simplified operator=
        *x = *(rhs.x);
        *y = *(rhs.y);
        *z = *(rhs.z);
    }
    int getx() const { return *x; }
    int gety() const { return *y; }
    int getz() const { return *z; }
    void setx(int _x) { *x = _x; }
    void sety(int _y) { *y = _y; }
    void setz(int _z) { *z = _z; }
    friend ostream& operator<< (ostream& out, const Coordinates& rhs) {
    out << "[" << *(rhs.x) << "," << *(rhs.y) << "," << *(rhs.z) << "]" << endl;
    return out;
    }

private:
    int *x, *y, *z;
}; //--------------------------------------------------------------



class CoordinatesList {
public:

    /*CoordinatesList &  operator=(const CoordinatesList &rhs)
    {

        if (size != rhs.size)
        {
            delete[] list;
            size = rhs.size;
            list = new Coordinates[size];
        }
        for (int i = 0; i < size; i++)
        {
            list[i].Coordinates::operator=(rhs.list[i]);
        }
        return *this;

    } */

    CoordinatesList operator=(const CoordinatesList & rhs) 
    {

        //check if sizes are differernt
        if (size != rhs.size) 
        {   
            delete[] list; //this calls ~coordinates 
            size = rhs.size; 
            list = new Coordinates[size]; 
        }
        //copy content      
        for (int i = 0; i < size; i++) {
            //list[i] = rhs.list[i]; 
//will work as operator= is defined for Coordinates
            list[i].setx(rhs.list[i].getx());
            list[i].sety(rhs.list[i].gety());
            list[i].setz(rhs.list[i].getz());
        }
        return *this; 
    }
    private:
    Coordinates * list;
    int size;
};
类坐标{//这是一个完整的类,不要修改它。
公众:
坐标(){
x=新整数;y=新整数;z=新整数;
*x=*z=*y=0;
}
坐标(整数x,整数y,整数z){
x=新整数;y=新整数;z=新整数;
*x=x;
*z=_y;
*y=_z;
}
坐标(常量坐标和rhs){//复制构造函数
x=新整数;y=新整数;z=新整数;
*x=*(rhs.x);
*y=*(rhs.y);
*z=*(rhs.z);
}
~Coordinates(){
删除x;删除y;删除z;
}
void运算符=(常量坐标和rhs){//简化运算符=
*x=*(rhs.x);
*y=*(rhs.y);
*z=*(rhs.z);
}
int getx()常量{return*x;}
int gety()常量{return*y;}
int getz()常量{return*z;}
void setx(int x){*x=x;}
void sety(int_y){*y=_y;}
void setz(int z){*z=z;}

friend ostream&operator使用CL=CoordinatesList;
在键入时进行保存

区别在于一个返回一个引用,一个返回一个副本。 惯用的方法是返回对
*this
的引用,因此使用以下方法:
CL&operator=(const CL&rhs){/*…*/return*this;}
请注意,定义这两个版本将导致编译器错误,因为函数不能仅因返回值不同而不同

运算符的用法=:

CL a = CL(<args>);// (1)
CL b,c;
b = a; // (2)
b.operator=(a); //(3)
c = b = a; // (4)
c.operator=(b.operator=(a)); // (5)
CL a=CL();/(1)
clb,c;
b=a;/(2)
b、 运算符=(a);/(3)
c=b=a;/(4)
c、 运算符=(b.运算符=(a));/(5)
(1) 不调用任何
CL::operator=
,而是调用构造函数
CL::CL()
。正在创建对象,因此无论等号如何,都必须调用构造函数

(2) 是(3)的唯一语法糖。调用
CL::operator=
并丢弃任何返回值


(4) 再一次,它是(5)的唯一语法糖。首先计算右侧的
运算符=
,并将返回值传递给左侧的
运算符=
作为其参数。在这种情况下,让
运算符=
返回副本确实会生成副本。这就是为什么首选第二个选项的原因,因为它不会产生额外和不必要的成本。这也应该如果函数返回
void
,那么这种语法就不可能了。

我很难想象使用
int*x,*y,*z;
over
intx,y,z;
的好理由。为什么在这里使用
list[I]。坐标::运算符=(rhs.list[I])当您可以编写
list[i]=rhs.list[i];
或getter和setter时;
?(这不是巧合,这是重载赋值操作的全部要点。)
CoordinatesList
还需要一个复制构造函数和析构函数来满足,一旦编写了复制构造函数并开始工作,您就可以利用将
运算符=
简单得惊人。为什么要在
CoordinatesList
中继承
坐标
?一个
坐标列表
是一种
坐标
,就像苹果车是一种苹果一样。借助@molbdnilo的注释。当你考虑继承时,应用.LSP是一个很好的快速过滤器。如果它检查出来,值得进一步研究。如果没有,就不要使用继承。