使用赋值运算符 =? 时 C++ 中的编译错误

Posted

技术标签:

【中文标题】使用赋值运算符 =? 时 C++ 中的编译错误【英文标题】:Compilation error in C++ when using an assignment operator =? 【发布时间】:2018-11-08 04:42:24 【问题描述】:

我编写了一个作为家庭作业交给我的程序(它有点长)。问题是它在 CodeBlocks 中编译,但在 Visual Studio 2017 中没有编译它说 - binary '=': no operator found which takes a right-hand operand of type 'CAutomobile' (or there is no acceptable conversion。 我想问为什么是因为我自己找不到错误?我尝试评论运营商=function,但错误仍然存​​在。

#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
using namespace std;
class CVehicle 
    string name;
    int year;
public:
    CVehicle() 
        name = "Car";
        year = 1990;
    
    CVehicle(string n, int y) 
        name = n;
        year = y;
    
    CVehicle(const CVehicle& vc) 
        name = vc.name;
        year = vc.year;
    
    void setName(string n) 
        name = n;
    
    void setYear(int y) 
        year = y;
    
    string getName() 
        return name;
    
    int& getYear() 
        return year;
    
    virtual void Print(ostream& os) = 0;
;
class CAutomobile :public CVehicle 
    double litres;
public:
    CAutomobile() :CVehicle() 
        litres = 7.2;
    
    CAutomobile(string nm, int yr, double l) :CVehicle(nm, yr) 
        litres = l;
    
    void setLitres(double l) 
        l = litres;
    
    double& getLitres() 
        return litres;
    
    void Print(ostream& os) override 
        os << getName() << endl;
        os << getYear() << endl;
        os << litres << endl;
    
    friend bool operator< (CAutomobile a1, CAutomobile a2) 
        if (a1.litres < a2.litres) 
            return true;
        
        return false;
    
    CAutomobile operator= (CAutomobile&  at) 
        CAutomobile au;
        au.getName() = at.getName();
        au.getYear() = at.getYear();
        au.getLitres() = at.getLitres();
        return au;
    
    CAutomobile operator+(CAutomobile aut) 
        CAutomobile a;
        a.getLitres() = getLitres() + aut.getLitres();
        return a;
    
    friend ostream& operator<< (ostream& o, CAutomobile a) 
        o << a.getName() << endl;
        o << a.getYear() << endl;
        o << a.getLitres() << endl;
        return o;
    
;
int main()

    CAutomobile a[] = 
    CAutomobile(),
    CAutomobile("Wolkswagen",1970,80.5),
    CAutomobile("Fiat",1979,21.9),
    CAutomobile("Opel",1978,13.7)
    ;
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) 
        cout << "Name" << ' ' << a[i].getName() << endl;
        cout << "Year" << ' ' << a[i].getYear() << endl;
        cout << "Litres" << ' ' << a[i].getLitres() << endl;
    
    int range = 2016 - 1990 + 1;
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) 
        a[i].setLitres(rand() % 100 + 1);
        a[i].setYear(rand() % range + 1996);
    
    //сортираме масива по литри и извеждаме 
    //най малкия (първия) му елемент
    for (int i = 0; i < sizeof(a-1); i++) 
        for (int j = 0; j < sizeof(a-1); j++) 
            if (a[j].getLitres() > a[j + 1].getLitres()) 
                swap(a[j], a[j + 1]);
            
        
       
    cout << a[0] << endl;
    CAutomobile k = a[0] + a[3];
    cout << k.getLitres() << endl;

【问题讨论】:

关于 Code::Blocks 的重要说明:它不进行编译。它位于第三方编译器之上,通常是 GCC 的一个版本,所以像这样的一些问题需要您追踪正在使用的 g++(GCC 的 C++ 编译器)的版本。通常,您可以通过打开终端窗口并输入 g++ -v 来获取此信息。 对于您的构造函数,请尝试使用 CVehicle() : name("Car"), year(1990) ... 等初始化列表。这可能会节省分配默认值。您还需要养成通过引用传递 string 之类的内容的习惯,以避免制作无休止、毫无意义的副本。 const string&amp; arg 是一个很好的默认值。 无关:在setLitres 中,l = litres; 几乎可以肯定是落后的。它将听起来像您想要设置的成员变量分配到一个自动变量中,该变量在函数末尾超出范围而没有任何用处。编译器可能会消除整个函数。可能会有关于此的编译器警告,如果没有,请提高警告级别。编译器警告是防止逻辑错误的第一道防线。 看看这里Programming a specific 3d (star-like) model in OpenGL?它有点像你删除的Question about modelling a specific 3d model?的重复... 【参考方案1】:

CAutomobile::operator = 完全错误。它接受一个非常量引用并将其字段分配给一个新对象。相反,它应该采用 const 引用并修改当前对象。

CAutomobile & operator =(CAutomobile const & other)

    assert(this != ::std::addressof(other)); // check for self-assignment
    SetName(other.getName());
    SetYear(other.getYear());
    SetLitres(other.getLitres());
    return *this;

这会带来另一个问题:getter 不是 const 限定的,所以它们也应该被修复:

string const & getName(void) const 
    return name;

int const & getYear(void) const 
    return year;

【讨论】:

另一个选项是流行的Copy and Swap Idiom,假设复制构造函数正常工作。如果你需要一个赋值运算符,三法则说你可能需要一个复制构造函数。注意:看起来也不需要此代码。 Read up on the Rule of Zero.

以上是关于使用赋值运算符 =? 时 C++ 中的编译错误的主要内容,如果未能解决你的问题,请参考以下文章

C++ 赋值运算符关于继承的问题

我应该为赋值运算符使用左值引用限定符吗?

c++ 拷贝构造函数与赋值运算符重载函数的区别是

c++ 默认赋值运算符

C++中赋值运算操作符和=重载有啥区别?

c++中拷贝构造函数和赋值运算符重载本质上一样么