Hi, I can't get the following code to work. I have my converting constructor (second line) to change an int type to a car type but my compiler says there's something wrong with the overloaded + operator.

It says here in my book that if I want to do an implicit type conversion:
1) The class must have an accessible converting constructor
2) The overloaded function must be nonmember (with or without friendship)

Let's suppose that the code given in the class is correct (b/c my teacher went over it two days ago and it was supposed to be correct. Don't think she checked it on the compiler though).

#include <iostream>

class car
{ 
public:
	car(int c = 0, char * name = "none") {}
	car(int c) : cost(c) { name = 0; }
	car(const car &);
	~car() { delete [] name; }
	car operator+ (const car &) { return *this; }
	car * fA (const car &) { return this; }
	car & operator= (const car &) { return *this; }
private:
	char * name;
	int cost;
};

car::car(const car & obj) : cost(obj.cost)
{
	this->name = new char[strlen(obj.name) + 1];
	strcpy( this->name, obj.name );
}

int main(void)
{
	car ford, vw;
	int a = 0;

	vw = ford + a;

	return 0;
}

Dani AI

Generated

Two distinct problems are causing the compile/runtime trouble: the pair of overlapping constructors and unsafe manual string handling. The book statement you quoted is often misunderstood — a member operator+(const car&) can accept an int on the right-hand side because the compiler may implicitly convert that int to a car using an accessible, non-explicit converting constructor. A nonmember operator+ is only required if you want conversions of the left-hand operand (for int + car).

Concrete fixes and recommendations:

  • Remove the ambiguous constructor overloads. A constructor with default parameters that can be called with a single int and a second constructor car(int) create an overload-resolution ambiguity. Keep a single converting constructor.
  • Stop using raw char* for name. In your code you set name = 0 in one constructor but the copy constructor calls strlen(obj.name), which is undefined behavior if name is null. Prefer std::string and the rule-of-zero: let the class use default copy/assignment/destructor.
  • If you need int + car as well as car + int, provide a nonmember overload for the swapped case.

A compact, safe pattern:

#include <string>

class car {
public:
    car(int cost = 0, const std::string& name = "none")
        : cost(cost), name(name) {}
    int getCost() const { return cost; }
    const std::string& getName() const { return name; }
private:
    std::string name;
    int cost;
};

inline car operator+(const car& a, const car& b) { return car(a.getCost() + b.getCost(), a.getName()); }
inline car operator+(const car& a, int x) { return car(a.getCost() + x, a.getName()); }
inline car operator+(int x, const car& a) { return operator+(a, x); }

Final tips: compile with warnings enabled (-Wall -Wextra) to see the ambiguous-constructor error clearly; if you must keep char*, implement a correct deep-copy copy ctor and assignment operator and guard against null pointers. was correct to flag the memory issue; resolving the constructor ambiguity fixes the operator+ compile error for your original ford + a expression.

Your overloaded + operator takes another car object's reference as an input, while the way you have used it in your program, it would require an overloaded operator which takes in an integer as input.

Your first two constructors are ambiguous since for a particular condition (when only cost is passed) both are eligible of being called.

Also, you should consider allocating memory to your name variable and using strcpy for copying them, rather than using a simple assignment operator which doesn't seem to cut ice in the case of C style strings.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.