简体   繁体   English

C ++ <

[英]C++ <<operator overloading with same type

I'm writing a method to print some spaces in std::cout , I know there are other ways using the standard library to achieve the same objective. 我正在编写一种在std::cout打印一些空格的方法,我知道还有其他方法可以使用标准库来实现相同的目标。 Anyway, I used a typedef to store the number of spaces and an overloading of the << operator. 无论如何,我使用typedef来存储空格数和<<操作符的重载。 But my overloading isn't called at all because my typedef is interpreted as an unsigned int. 但是我的重载根本没有被调用,因为我的typedef被解释为一个无符号的int。

So how can I tell to the compiler to call my function instead ? 那么,如何告诉编译器调用我的函数呢?

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

This is the expected output: 这是预期的输出:

K     X

This is the output I obtain: 这是我获得的输出:

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 doesn't create new type, it just creates alias of existing type. Typedef不会创建新类型,它只会创建现有类型的别名。 Possbile you could use something like this: 可能您会使用以下内容:

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;

Since you're defining space_type as an alias (ie typedef) and not a type, it is not distinguishable from int , and the compiler will issue an error if you attempted to overload operator(std::ostream&, int) . 由于您将space_type定义为别名 (即typedef)而不是类型,因此无法将其与int区分开,并且如果您尝试重载operator(std::ostream&, int) ,则编译器将发出错误。

But what you're doing is defining a class member: 但是您要做的是定义一个类成员:

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

When you define operators as class members, the first argument to the operator is (implicitly) an instance of the class. 当您将运算符定义为类成员时,运算符的第一个参数是(隐式地)该类的实例。 So in principle, that could only be called with: 因此,原则上只能用以下方式调用:

MyClass m;
m << ???

But here is a problem: an operator function called using infix notation can only have two parameters, and in the case of a member operator function, the first argument is implicit. 但这是一个问题:使用中缀表示法调用的运算符只能有两个参数,对于成员运算符,第一个参数是隐式的。 m << x can only be implemented by MyClass::operator<<(decltype(x)) . m << x只能由MyClass::operator<<(decltype(x))

In short, you can only implement this with a non-member operator<< and the second argument to that overload must be a user type. 简而言之,您只能使用非成员operator<<来实现此目的,并且该重载的第二个参数必须是用户类型。 So the following will work fine: 因此,以下将正常工作:

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

See it on ideeone ideeone看到

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM