Compilation error in C++ when using an assignment operator =?

3529 views c++
0

I have written a program which was given to me as a homework assignment (it's a bit longer). The issue is that it compiles in CodeBlocks but it does not compile in Visual Studio 2017 it says - binary '=': no operator found which takes a right-hand operand of type 'CAutomobile' (or there is no acceptable conversion. I would like to ask why is that because I could not myself find the error? I tried commenting the operator =function but still the error remained.

#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;
}

answered question

Important note about Code::Blocks: It doesn't do the compiling. It sits over a third party compiler, usually a version of GCC, so some questions like this will require you to track down the version of g++ (GCC's C++ compiler) being used. Usually you can get this by opening a terminal window and typing g++ -v.

For your constructor try and use the initializer lists like CVehicle() : name("Car"), year(1990) { ... }. This saves potentially assigning a default value. You'll also want to get into the habit of passing in things like string via reference to avoid making endless, pointless copies. const string& arg is a good default to use.

Unrelated: in setLitres, l = litres; is almost certainly backward. It's assigning the member variable that it sound like you want set, into an Automatic variable that goes out of scope at the end of the function to no useful effect. The compiler will probably eliminate the whole function. There may be a compiler warning about this, and if not, crank up the warning level. Compiler warnings are the first line of defense against logic errors.

1 Answer

13

CAutomobile::operator = is completely wrong. It takes a non-const reference and assignes its field to a new object. Instead it should take a const reference and modify current object.

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;
}

This will bring up another problem: getters are not const-qualified, so they should be fixes as well:

string const & getName(void) const {
    return name;
}
int const & getYear(void) const {
    return year;
}

posted this

Have an answer?

JD

Please login first before posting an answer.