链接器错误 - 朋友和左手边。 (没有模板)

时间:2011-01-24 01:03:20

标签: c++ operator-overloading linker-errors

这是在程序中抛出错误的行:(s和u是统计对象)

s = 2*u;

错误C2678:二进制'*':找不到哪个运算符带有'int'类型的左操作数(或者没有可接受的转换)

这是标头文件:

#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

这是c ++文件:

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

当我在标题和实现中取消注释两个运算符时,会出现链接器错误:

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

我找不到任何东西,我想我已经尝试了一切。我在Win 7 x64 Professional上使用VS 2010 x64 Professional。

1 个答案:

答案 0 :(得分:5)

似乎你已经正确地认识到你需要在左侧提供另一个带有double的重载。带有(统计学家,双重)的op *重载对(double,statistician)不起作用。

  

当我在标头和实现中取消注释两个运算符时,它会给链接器错误。

您的项目设置配置错误,并且您没有链接到定义这些设置的实现文件。或者,您的构建可能是错误配置的,并且无法识别您已修改这些文件并且需要重建它们。 “make clean”/“rebuild all”将暂时解决后一个问题。

我的第一个想法是错误的,问题是命名空间指令。您在实现文件中实际执行的操作是在另一个命名空间中定义另一个运算符重载。这使得main_savitch_2C命名空间中的重载保持为未定义。而不是“使用命名空间X;”,将实现文件包装在“命名空间X {”和“}”中。

这是一个展示问题的小例子。它包含在一个文件中,因此不会发生多TU链接问题。

namespace a {
struct B {};
int operator+(B, int x);
}

using namespace a;

int main() {
  B() + 42;
  return 0;
}

int operator+(B, int) { return 0; }

如果最后一行高于main,则main中的表达式将不明确,最清楚地表明您已定义了单独的运算符重载:

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)

通常,避免使用指令。 (使用指令是“使用命名空间X;”;使用声明是“使用X :: name;”,这很好。)但是,指令在本地函数范围(我经常使用它们的唯一地方)中很有用:

void example() {
  using namespace std;  // scoped to function
  cout << "blah\n";
}

顺便说一句,这就是我如何定义重载,假设* =对统计数据类型有意义,当你使用*时通常会这样做:

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