Reputation: 6307
This is the line that is throwing the error in the program: (s and u are statistician objects)
s = 2*u;
error C2678: binary '*' : no operator found which takes a left-hand operand of type 'int' (or there is no acceptable conversion)
This is the header file:
#ifndef STATISTICIAN
#define STATISTICIAN
namespace main_savitch_2C
{
class statistician
{
protected:
int _length;
double _mean, _minimum, _maximum;
public:
statistician();
statistician(int length, double mean,
double min, double max);
void next_number(double num);
void reset();
int length() const;
double sum() const;
double mean() const;
double minimum() const;
double maximum() const;
friend statistician operator*(
const statistician& a, double x);
//friend statistician operator*(
// double x, const statistician& a);
};
bool operator== (
const statistician& a,
const statistician& b);
statistician operator+ (
const statistician& a,
const statistician& b);
}
#endif STATISTICIAN
This is the c++ file:
#include "statistician.h"
using namespace main_savitch_2C;
statistician::statistician()
{
reset();
}
statistician::statistician(int length,
double mean, double min, double max)
{
_length = length;
_mean = mean;
_minimum = min;
_maximum = max;
}
void statistician::next_number(double num)
{
_mean = (_mean * _length + num) /
++_length;
if (num < _minimum) _minimum = num;
if (num > _maximum) _maximum = num;
}
void statistician::reset()
{
_length = _mean = _minimum =
_maximum = 0;
}
int statistician::length() const
{
return _length;
}
double statistician::sum() const
{
return _mean * _length;
}
double statistician::mean() const
{
return _mean;
}
double statistician::minimum() const
{
return _minimum;
}
double statistician::maximum() const
{
return _maximum;
}
bool operator==(const statistician& a,
const statistician& b)
{
return (a.length()==b.length())
&& (a.mean()==b.mean())
&& (a.minimum()==b.minimum())
&& (a.maximum()==b.maximum());
}
statistician operator+ (
const statistician& a,
const statistician& b)
{
return statistician(
a.length() + b.length(),
(a.sum() + b.sum()) /
(a.length() + b.length()),
(a.minimum() < b.minimum()) ?
a.minimum() : b.minimum(),
(a.maximum() > b.maximum()) ?
a.maximum() : b.maximum());
}
statistician operator* (
const statistician& a, double x)
{
return statistician(
a.length() * x,
a.mean() * x,
a.minimum() * x,
a.maximum() * x);
}
//statistician operator* (double x,
// const statistician& a)
//{
// return statistician(
// a.length() * x,
// a.mean() * x,
// a.minimum() * x,
// a.maximum() * x);
//}
When I uncomment the two operators in the header and the implementation, it gives linker errors:
error LNK2019: unresolved external symbol "bool __cdecl main_savitch_2C::operator==(class main_savitch_2C::statistician const &,class main_savitch_2C::statistician const &)" (??8main_savitch_2C@@YA_NABVstatistician@0@0@Z) referenced in function "int __cdecl test3(void)" (?test3@@YAHXZ)
error LNK2019: unresolved external symbol "class main_savitch_2C::statistician __cdecl main_savitch_2C::operator+(class main_savitch_2C::statistician const &,class main_savitch_2C::statistician const &)" (??Hmain_savitch_2C@@YA?AVstatistician@0@ABV10@0@Z) referenced in function "int __cdecl test3(void)" (?test3@@YAHXZ)
error LNK2019: unresolved external symbol "class main_savitch_2C::statistician __cdecl main_savitch_2C::operator*(double,class main_savitch_2C::statistician const &)" (??Dmain_savitch_2C@@YA?AVstatistician@0@NABV10@@Z) referenced in function "int __cdecl test4(void)" (?test4@@YAHXZ)
error LNK1120: 3 unresolved externals
I can't find anything, and I think I've tried everything. I'm using VS 2010 x64 Professional, on Win 7 x64 Professional.
Upvotes: 1
Views: 455
Reputation: 14212
It seems you've rightly recognized that you need to provide another overload with double on the left-hand side. The op* overload with (statistician, double) does not work for (double, statistician).
When I uncomment the two operators in the header and the implementation, it gives linker errors.
Your project settings are misconfigured, and you're not linking with the implementation file that defines these. Or, possibly, your build is misconfigured and doesn't recognize that you've modified these files and that they need to be rebuilt. A "make clean" / "rebuild all" will temporarily fix the latter problem.
My first thought was wrong, the problem is the namespace directive. What you actually do in the implementation file is define another operator overload in a different namespace. This leaves the overload in the main_savitch_2C namespace as undefined. Instead of "using namespace X;", wrap the implementation file in "namespace X {" and "}".
Here's a small example which demonstrates the problem. It is contained within one file, so multiple-TU linking problems can't occur.
namespace a {
struct B {};
int operator+(B, int x);
}
using namespace a;
int main() {
B() + 42;
return 0;
}
int operator+(B, int) { return 0; }
If the last line had been above main, the expression in main would be ambiguous, which most clearly shows you have defined a separate operator overload:
example.cpp:8: error: ambiguous overload for ‘operator+’ in ‘a::B() + 42’
example.cpp:6: note: candidates are: int operator+(a::B, int)
example.cpp:3: note: int a::operator+(a::B, int)
In general, avoid using directives. (Using directives are "using namespace X;"; using declarations are "using X::name;", which are fine.) However, directives are useful in a local function scope (the only place I use them often):
void example() {
using namespace std; // scoped to function
cout << "blah\n";
}
Incidentally, this is how I would define the overloads, assuming that *= makes sense for the statistician type, which it usually does when * is used in the way you use it:
struct statistician {
//...
statistician& operator*=(double x) {
// likely defined in implementation file, defined inline here for example
_length *= x;
_mean *= x;
_minimum *= x;
_maximum *= x;
return *this;
}
};
// usually defined inline in the header
inline
statistician operator*(double a, statistician b) {
b *= a;
return b;
}
inline
statistician operator*(statistician a, double b) {
a *= b;
return a;
}
Upvotes: 5