【问题标题】:Compilation error in C++ when using an assignment operator =?使用赋值运算符 =? 时 C++ 中的编译错误
【发布时间】: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; 几乎可以肯定是落后的。它将听起来像您想要设置的成员变量分配到一个自动变量中,该变量在函数末尾超出范围而没有任何用处。编译器可能会消除整个函数。可能会有关于此的编译器警告,如果没有,请提高警告级别。编译器警告是防止逻辑错误的第一道防线。

标签: c++ visual-studio oop compiler-errors


【解决方案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.
猜你喜欢
  • 2014-02-08
  • 2012-08-13
  • 1970-01-01
  • 1970-01-01
  • 2019-08-22
  • 2015-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多