1

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;
}
  • 1
    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`. – user4581301 Nov 08 '18 at 04:46
  • 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. – tadman Nov 08 '18 at 04:47
  • 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. – user4581301 Nov 08 '18 at 04:52
  • take a look here [Programming a specific 3d (star-like) model in OpenGL?](https://stackoverflow.com/a/53564088/2521214) its a sort of a duplicate to your deleted [Question about modelling a specific 3d model?](https://stackoverflow.com/q/53204972/2521214) ... – Spektre Nov 30 '18 at 22:28

1 Answers1

2

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;
}
user7860670
  • 35,849
  • 4
  • 58
  • 84
  • 1
    Another option is the ever-popular [Copy and Swap Idiom](https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom), assuming the Copy Constructor works correctly. And if you need an assignment operator, the Rule of Three says you probably need a Copy Constructor. Note: Doesn't look like this code needs either. [Read up on the Rule of Zero.](https://en.cppreference.com/w/cpp/language/rule_of_three) – user4581301 Nov 08 '18 at 04:54