相同类型的C++ <<运算符重载

C++ <<operator overloading with same type

本文关键字:lt 运算符 重载 同类型 C++      更新时间:2023-10-16

我正在写一个方法来打印std::cout中的一些空间,我知道还有其他方法可以使用标准库来实现同样的目标。无论如何,我使用了一个typedef来存储空间的数量和<<运算符的重载。但是我的重载根本没有被调用,因为我的typedef被解释为一个无符号的int

那么,我该如何告诉编译器调用我的函数呢?

class MyClass {
private: 
  typedef unsigned int space_type;
public: 
  std::ostream& operator<< (std::ostream& _os, space_type _n_spaces) {
    for (int _C = 0; _C < _n_spaces; _C++) 
      _os << " ";
    return _os;
  }
  void PrintNumbers(char _a, char _b) {
    space_type spaces = 5;
    std::cout << _a << spaces << _b << std::endl;
  }
}
int main () {
  MyClass class_instance;
  class_instance.PrintNumbers('K', 'X');
  std::cin.get();
  return 0;
}

这是预期输出:

K     X

这是我获得的输出:

K5X  // 5 is interpreted as an unsigned int, so my overloaded function 
     // isn't called, instead is called the std overloading with unsigned int

Typedef不创建新类型,它只创建现有类型的别名。你可能会使用这样的东西:

struct SpaceType {
    int space_cnt;
};
...
std::ostream& operator<< (std::ostream& _os, SpaceType _n_spaces) {
    for (int _C = 0; _C < _n_spaces.space_cnt; _C++) 
      _os << " ";
    return _os;
  }
...  
SpaceType spaces = { 5 };
std::cout << _a << spaces << _b << std::endl;

由于您将space_type定义为别名(即typedef)而不是类型,因此它与int无法区分,如果您试图重载operator(std::ostream&, int),编译器将发出错误。

但你正在做的是定义一个类成员:

std::ostream& operator<< (std::ostream& _os, space_type _n_spaces)

当您将运算符定义为类成员时,运算符的第一个参数是(隐式)类的实例。因此,原则上,这只能用调用

MyClass m;
m << ???

但这里有一个问题:使用中缀表示法调用的运算符函数只能有两个参数,而在成员运算符函数的情况下,第一个参数是隐式的。m << x只能由MyClass::operator<<(decltype(x))来实现。

简而言之,您只能使用非成员operator<<来实现这一点,并且该重载的第二个参数必须是用户类型。因此以下操作会很好:

struct space_t {
   unsigned x;
   space_t(unsigned x) : x(x) {}
   operator unsigned() const { return x; }
};
std::ostream& operator<< (std::ostream& os, space_t n) {
  for (unsigned i = 0; i < n; ++i) os << " ";
  return os;
}

在ideeone 上查看