何处放置重载<<码?

时间:2012-11-22 16:24:09

标签: c++ operator-overloading

我正在尝试为一个已经有toString()函数返回字符串的类Foo重载流操作符<<,并使用以下代码:

std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
    flux <<  foo.toString(); 
    return flux;
}

要在main.cpp文件

中使用它

我的问题是:在哪里放一段代码?

  • 如果我将它放在main.cpp中,在使用之前,它运行良好,但我可能想在其他文件中使用它。
  • 如果我将其放在foo.cpp中,我会收到“没有这样的功能”错误:

    src/main.cpp:77: error: no match for ‘operator<<’ in ‘std::cout << foo’
    

    这是有道理的,因为代码未包含在main.cpp文件

  • 如果我将它放在foo.h类标题中,在类声明之外,我会收到'多重定义'错误:

    foo.o: In function `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Foo const&)':
    foo.cpp:(.text+0x0): multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Matrix const&)'
    bar.o:bar.cpp:(.text+0x0): first defined here
    

    foo.h标题确实包含在不同的类/文件中,但是有一个ifdef保护,所以我不明白这一点。

那我该怎么办?

5 个答案:

答案 0 :(得分:9)

有多种选择:

Foo之后的标头中声明它,并在Foo.cpp中定义它。

//foo.h
class Foo
{};
std::ostream &operator<<( std::ostream &s, Foo const& foo );

//foo.cpp
#include "foo.h"
std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
    return s;
}

在类定义中将其定义为friend

//Foo.h
class Foo
{
   friend std::ostream &operator<<( std::ostream &s, Foo const& foo )
   {
      return s;
   }
};

在类定义之外的标题中定义它,并将其标记为inline以防止多重定义。

//Foo.h
class Foo
{
};

inline std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
   return s;
}

答案 1 :(得分:4)

通过类声明放置重载的原型,在Foo实现中实现(或者如果你想要它inline,将它放在Foo声明中)。< / p>

所以:

// foo.h
#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
std::ostream& operator<< (std::ostream &, Foo const &);
#endif // FOO_H_ASDSADKJSLADJL

// foo.cpp
#include "foo.h"
....
std::ostream& operator<< (std::ostream &os, Foo const &) {
    ....
    return os;
}

#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
inline std::ostream& operator<< (std::ostream &os, Foo const &) {
    ....
    return os;
}
#endif // FOO_H_ASDSADKJSLADJL

编译器找不到它的错误是缺少原型的重载。

答案 2 :(得分:4)

将声明放在头文件中,将定义放在cpp文件中。

即,放

std::ostream &operator<<( std::ostream &flux, Foo const& foo );
在您的头文件中

,然后输入

std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
    flux <<  foo.toString(); 
    return flux;
}

在您的cpp文件中。

这样,您可以在任何地方包含头文件,并且可以使用该功能,但只会定义一次,因此您不会收到multiple definitions错误。

答案 3 :(得分:0)

在标头中声明它,您在其中声明Foo,在源中定义它,您可以在其中定义Foo方法。

答案 4 :(得分:0)

因为使用C和C ++,你应该

  1. 将实际代码放入相应的.c / .cpp文件中 - 我建议foo.cpp
  2. 预先声明放入相应的.h / .hpp头文件中,并为主要c /外部使用的所有内容提供适当的#ifdef保护cpp文件。
  3. 在某些情况下,您可以使用#define宏或inline功能。然后应该在标题中完成;由于内联,不应该有多重声明错误。

    技术上你可以做很多事情。我建议坚持在头文件中定义API的最佳实践,并将实现放入代码文件中。这是最具扩展性的。 inline hack适用于这种情况,但如果您稍后决定增强该方法并删除内联,则会出乎意料地中断。

    标题/代码拆分最不容易破解。