简体   繁体   English

了解operator()重载

[英]Understanding operator() overloading

I'm trying to understand overloading method, especially concerning bool operator(). 我正在尝试了解重载方法,尤其是关于布尔运算符()。 Please, try to be understanding. 请尝试理解。 I did try to read some articles about overloading operators but still can't get it ;/ 我确实尝试阅读一些有关重载运算符的文章,但仍然无法理解; /

I have the set container from STL, which automatically sorts its' 'objects' in alphabetic order, but I would like to modify it so that it will sort string according to their length. 我有来自STL的set容器,该容器自动按字母顺序对它的“对象”进行排序,但是我想对其进行修改,以便它将根据其长度对字符串进行排序。

Here's working code, which I struggle to understand 这是工作代码,我很难理解

#include <iostream>
#include <set> 
#include <iterator>

using namespace std; 

struct MyOrder
{
   bool operator()(const string &first, const string &second) 
   { 
      int length1 = first.length(); //** assigning length of strings (arguments)
                                    //** to int, so that we will compare their lengths

      int length2 = second.length(); //** same story**//

      if(length1 == length2) //** if both strings are the same length, code will return  
                             //** true, but what does is mean first < second ?, will it 
                                  swap places of arguments or what ? 
         return (first < second); 

      return (length1 < length2); //** same story, if they are not the same length, than    
                                  //** what ? return true, and swap arguments' places ? 
    } 
  } 

int main(void) 
{
   set<string, Myorder> names; 

   names.insert("Tony Soprano"); 
   names.insert("Christopher Moltisanti"); 

   set<string>::iterator it; 

   for(it = names.begin(); it != names.end(); ++it) 
   { 
      cout << *it << endl; 
   } 
 } 

The second template parameter to set<> , if provided, is an operator that determines how you want elements ordered. set<>的第二个模板参数(如果提供)是一个运算符,用于确定元素的排序方式。 The default operator is the result of using std::less<> , which will return true if the first argument is less than the second argument. 默认运算符是使用std::less<>的结果,如果第一个参数小于第二个参数,则返回true。 When using the default comparison operator, elements e 0 .. e N in the set will be ordered such that e i < e i+1 is true. 使用默认比较运算符时,集合中的元素e 0 .... e N将被排序,以使e i < e i + 1为真。

The operator overload of () enables an instance of MyOrder to be invoked as if it was a function. 操作符()重载使MyOrder实例可以被当作函数调用。 By providing MyOrder as the second template parameter, you are changing the order of the elements in the set to be so that if order is an instance of MyOrder , order( e i , e i+1 ) is true. 通过提供MyOrder作为第二个模板参数,您可以将集合中元素的顺序更改为,以便如果orderMyOrder的实例, order( e ie i + 1 )为true。

MyOrder has been implemented to behave as follows: MyOrder已实现为具有以下行为:

  • If the two arguments are of equal length, return the result of first < second . 如果两个参数长度相等,则返回first < second的结果。
    -- This means that if the strings are of equal length, return true if the first string is alphabetically less than the second, and false otherwise. -这意味着如果字符串长度相等,则如果第一个字符串按字母顺序小于第二个字符串,则返回true,否则返回false。

  • If the two arguments are not equal in length, return true if first is shorter than the second , and false otherwise. 如果两个参数的长度不相等,则如果first短于second参数,则返回true,否则返回false。

How set<> maintains ordering of the elements is an implementation detail, but it does so as you add new elements. set<>如何保持元素的顺序是实现细节,但是在添加新元素时会如此。 Initially, when there are no elements, there is no restriction for adding the first element. 最初,当没有元素时,添加第一个元素没有限制。 As each new element is added, it is added as if it had been compared to all the existing elements using the provided operator to determine its correct relative position. 添加每个新元素时,就好像使用已提供的运算符将其与所有现有元素进行比较一样来添加它,以确定其正确的相对位置。

So if the set contained { "m", "zz", "aaa" } , and you want to add "ii" to it, it would be placed after "m" (since it is longer than it), but before "zz" (since it is alphabetically less than it). 因此,如果集合包含{ "m", "zz", "aaa" } ,并且您想向其中添加"ii" ,则它将被放置在"m" (因为它比它长),但是要放在"m"之前"zz" (因为按字母顺序比它小)。 So the result would become { "m", "ii", "zz", "aaa" } . 因此结果将变成{ "m", "ii", "zz", "aaa" }

The < operator means less than and it evaluates to true or false . <运算符的意思是小于,并且其计算结果为truefalse For example: 例如:

3 < 4    // true
6 < 5    // false
7 < 7    // false

It doesn't "swap the arguments" or anything. 它不会“交换参数”或其他任何东西。

When applied to a class type such as std::string , operators such as < call the overloaded operator< function for that class. 当应用于诸如std::string类的类类型时,诸如<operator<调用该类的重载operator<函数。 For std::string , it has that operator overloaded to do a lexicographical comparison, ie dictionary order. 对于std::string ,该操作符已重载以进行字典比较,即字典顺序。 For example: 例如:

string("computer") < string("dog")     // true
string("a") < string("abc")            // true

The other thing to understand is how the std::sort (and other standard containers' sorting) uses operator< . 要理解的另一件事是std::sort (和其他标准容器的排序)如何使用operator< The rules are: 规则是:

  • if a < b it means that a comes earlier in the sort order than b 如果a < b则表示a在排序顺序上早于b
  • otherwise, either a comes later than b , or a and b are equal in the sort order. 否则, a会晚于b ,或者ab在排序顺序上相等。

If it needs to distinguish the last two cases (ie whether whether a comes later than b , or whether they're equal) it can check b < a . 如果需要区分最后两种情况(即无论是否a来晚于b ,或者它们是否相等),它可以检查b < a If a < b && b < a it means that they are equal. 如果a < b && b < a表示它们相等。

Don't worry about which sorting algorithm is being used, or how it does its thing. 不必担心正在使用哪种排序算法,或者它是如何工作的。 Your code just needs to make sure that its operator< function returns false or true as just described. 您的代码只需要确保其operator<函数返回如前所述的falsetrue The sorting algorithm will use that information to produce the sorted result. 排序算法将使用该信息来产生排序结果。

So, going back to the line you are looking at in your code: 因此,回到您在代码中查看的行:

if(length1 == length2)
     return (first < second); 

return length1 < length2;

It means: 它的意思是:

  • If the lengths are not equal, then the shorter one comes first in the sort order 如果长度不相等,则较短的长度按排序顺序排在首位
  • If the lengths are equal, then the one that comes first in the dictionary comes first in the sort order. 如果长度相等,则字典中排在第一位的将按排序顺序排在第一位。

So if the set was dog car cheese boat dog then the sorted order is car dog dog boat cheese . 因此,如果设置的是dog car cheese boat dog那么排序的顺序是car dog dog boat cheese dog car cheese boat dog

Questions in comments area shows that you expect MyOrder::operator() to swap actual elements. 注释区域中的问题表明您希望MyOrder::operator()交换实际元素。 This is not true. 这不是真的。 Your MyOrder functor used to compare values in internals of std::set , which you do not need to know. 您的MyOrder函子用于比较std::set内部的值,您无需知道这些值。 This way you can abstract of details of implementation of std::set and just provide your sorting criteria in form of MyOrder functor. 这样,您可以抽象std::set的实现细节,并仅以MyOrder函子形式提供排序条件。 So you can use the same functor for example for std::sort : 因此,您可以为std::sort使用相同的仿函数:

int main(void) 
{
   std::vector< std::string> names; 

   names.push_back("Tony Soprano"); 
   names.push_back("Christopher Moltisanti"); 

   std::sort( names.begin(), names.end(), MyOrder() );
   std::vector<std::string>::iterator it; 

   for( it = names.begin(); it != names.end(); ++it) 
   { 
      std::cout << *it << std::endl; 
   } 
}

and do not need to know how std::sort is moving elements around. 并且不需要知道std::sort如何移动元素。

The operator overload of operator() enables an instance of your class MyOrder to be invoked as if it was a function. operator()的运算符重载使类MyOrder的实例可以被当作函数调用。 A class with operator() is also called a functor . 具有operator()类也称为函子 () is application operator. ()应用运算符。

You can apply this way custom sort criterion to algorithm - std::sort will use a call to MyOrder::operator()( std::string, std::string) on an instance of your class MyOrder to ask about how to treat these two strings. 您可以通过这种方式将自定义排序条件应用于算法MyOrder::operator()( std::string, std::string) std::sort将在类MyOrder的实例上使用对MyOrder::operator()( std::string, std::string)MyOrder以询问如何处理这两个字符串。

Now we will sort based on length and using alphabetic order in case of equal length. 现在,我们将基于长度进行排序,并在长度相等的情况下使用字母顺序。

#include <iostream>
#include <set> 
#include <iterator>


struct MyOrder
{
   bool operator()( const std::string &first, const std::string &second) 
   { 
      size_t length1 = first.length();
      size_t length2 = second.length();
      if ( length1 == length2) return first < second;
      return ( length1 < length2);
   }
};

the rest as before (with some error correction, MyOrder instead Myorder) 其余的和以前一样(有一些错误纠正,用MyOrder代替Myorder)

int main(void) 
{
   std::set< std::string, MyOrder> names; 

   names.insert("Tony Soprano"); 
   names.insert("Christopher Moltisanti"); 

   std::set<std::string>::iterator it; 

   for( it = names.begin(); it != names.end(); ++it) 
   { 
      std::cout << *it << std::endl; 
   } 
}

http://ideone.com/1zTAn7 http://ideone.com/1zTAn7

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

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