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

Cal*_*res 1 c++ operator-overloading linker-errors

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

s = 2*u;
Run Code Online (Sandbox Code Playgroud)

错误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
Run Code Online (Sandbox Code Playgroud)

这是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);
//}
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

Fre*_*urk 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; }
Run Code Online (Sandbox Code Playgroud)

如果最后一行高于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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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;
}
Run Code Online (Sandbox Code Playgroud)