首页 \ 问答 \ 为什么operator <是非成员函数?(Why should operator< be non-member function?)

为什么operator <是非成员函数?(Why should operator< be non-member function?)

我记得C++ Primer告诉我们operator<应该non-member function ,我总是遵守规则。 但现在我想知道原因。

我写了以下代码:

#include <iostream>
using std::cout;
using std::endl;

struct Point1
{
  int x, y;
  Point1(const int a, const int b): x(a), y(b) { }
};
inline bool operator<(const Point1& lhs, const Point1& rhs)
{
  return lhs.x < rhs.x || (lhs.x == rhs.x && lhs.y < rhs.y);
}

struct Point2
{
  int x, y;
  Point2(const int a, const int b): x(a), y(b) { }
  bool operator<(const Point2& rhs)
  {
    return x < rhs.x || (x == rhs.x && y < rhs.y);
  }
};

int main()
{
  Point1 a(1, 2), b(1, 3);
  cout << (a < b) << " " << (b < a) << endl;
  Point2 c(2, 3), d(2, 4);
  cout << (c < d) << " " << (d < c) << endl;
}

在这种情况下,似乎它们没有区别, member函数似乎更简单。

但在这种情况下:

#include <iostream>
using std::cout;
using std::endl;

 // Usually I write it for comparing floats
class Float1
{
  long double _value;
public:
  static const long double EPS = 1e-8;
  Float1(const long double value): _value(value) { }
  const long double Get() const { return _value; }
};
inline bool operator<(const Float1& lhs, const Float1& rhs)
{
  return rhs.Get() - lhs.Get() > Float1::EPS;
}
inline bool operator<(const Float1& lhs, const long double rhs)
{
  return rhs - lhs.Get() > Float1::EPS;
}

class Float2
{
  long double _value;
public:
  static const long double EPS = 1e-8;
  Float2(const long double value): _value(value) { }
  const long double Get() const { return _value; }
  bool operator<(const Float2& rhs)
  {
    return rhs._value - _value > Float2::EPS;
  }
  bool operator<(const long double rhs)
  {
    return rhs - _value > Float2::EPS;
  }
};

int main()
{
  Float1 x(3.14);
  Float2 y(2.17);
  long double zero = .0;
  cout << (x < zero) << " " << (zero < x) << endl;
  //cout << (y < zero) << " " << (zero < y) << endl; Compile Error!
}

(x <零)和(零<x)都有效! ( long double转换为Float ?)

但是(零<y)不,因为零不是Float

您可以看到,在第一种情况下, member function成本较少,而在第二种情况下, non-member function使得比较更容易。 所以我想知道

  • 在第一种情况下,我应该使用member function而不non-member function吗?
  • 为什么C++ Primer建议binary operator non-member function
  • member functionnon-member function有什么区别吗?

谢谢你的帮助!


I remeber C++ Primer tells us operator< should be non-member function, and I always obey the rule. But now I want to know the reason.

I wrote following code:

#include <iostream>
using std::cout;
using std::endl;

struct Point1
{
  int x, y;
  Point1(const int a, const int b): x(a), y(b) { }
};
inline bool operator<(const Point1& lhs, const Point1& rhs)
{
  return lhs.x < rhs.x || (lhs.x == rhs.x && lhs.y < rhs.y);
}

struct Point2
{
  int x, y;
  Point2(const int a, const int b): x(a), y(b) { }
  bool operator<(const Point2& rhs)
  {
    return x < rhs.x || (x == rhs.x && y < rhs.y);
  }
};

int main()
{
  Point1 a(1, 2), b(1, 3);
  cout << (a < b) << " " << (b < a) << endl;
  Point2 c(2, 3), d(2, 4);
  cout << (c < d) << " " << (d < c) << endl;
}

In this case, It seems they don't make difference and member function seems much simpler.

But in this case:

#include <iostream>
using std::cout;
using std::endl;

 // Usually I write it for comparing floats
class Float1
{
  long double _value;
public:
  static const long double EPS = 1e-8;
  Float1(const long double value): _value(value) { }
  const long double Get() const { return _value; }
};
inline bool operator<(const Float1& lhs, const Float1& rhs)
{
  return rhs.Get() - lhs.Get() > Float1::EPS;
}
inline bool operator<(const Float1& lhs, const long double rhs)
{
  return rhs - lhs.Get() > Float1::EPS;
}

class Float2
{
  long double _value;
public:
  static const long double EPS = 1e-8;
  Float2(const long double value): _value(value) { }
  const long double Get() const { return _value; }
  bool operator<(const Float2& rhs)
  {
    return rhs._value - _value > Float2::EPS;
  }
  bool operator<(const long double rhs)
  {
    return rhs - _value > Float2::EPS;
  }
};

int main()
{
  Float1 x(3.14);
  Float2 y(2.17);
  long double zero = .0;
  cout << (x < zero) << " " << (zero < x) << endl;
  //cout << (y < zero) << " " << (zero < y) << endl; Compile Error!
}

Both (x < zero) and (zero < x) work! (is long double converted to Float?)

But (zero < y) don't, because zero is not a Float.

You see, in first case, member function costs less code length, and in second case, non-member function makes comparing easier. So I want to know

  • In first case, should I use member function instead of non-member function?
  • Why C++ Primer suggests binary operators be non-member function?
  • Is there any other case that member function and non-member function make difference?

Thanks for helping!


原文:https://stackoverflow.com/questions/12047174
更新时间:2024-05-06 06:05

最满意答案

我想我发现了这个问题。 每次我们调整下一个嵌套窗口的大小时,内核堆栈都会增加,直到它没有enougth堆栈来调用wndproc并且我们停止接收消息。

更多细节可以在这里找到: http//blogs.msdn.com/b/alejacma/archive/2008/11/20/controls-won-t-get-resized-once-the-nesting-hierarchy-of-windows -exceeds-A-一定深度-x64.aspx


I think I found the problem. Each time we resize the next nested window the kernel stack increases until it doesn't have enougth stack to call the wndproc and we stop receiving messages.

More details can be found here: http://blogs.msdn.com/b/alejacma/archive/2008/11/20/controls-won-t-get-resized-once-the-nesting-hierarchy-of-windows-exceeds-a-certain-depth-x64.aspx

相关问答

更多
  • 当您响应WM_ERASEBKGND您必须return TRUE ,否则您的默认对话框过程会将对话框的颜色设置为默认的系统颜色。 另外,调用SelectObject第二个参数是错误的,它应该是TRANSPARENT ,而不是TRANSPARENTE。 正如成员arx所说,你需要处理WM_CTLCOLORDLG消息来实现你想要的。 这是一个小型演示应用程序,您可以将其复制并粘贴到Visual Studio中: 在你的resource.h粘贴这个: //{{NO_DEPENDENCIES}} // Microso ...
  • 得到它了。 问题是我不知道用于SHBrowseForFolder的回调函数与窗口本身的回调不同。 它出来我必须做另一个函数来子类化对话框。 它是UGLY和不安全的代码,但它编译并说明了原理。 #include #include WNDPROC origBffProc; LRESULT CALLBACK bffProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static HBRUSH ...
  • 以下是一些尝试的建议: 将单击事件添加到子窗体,然后单击调用Show()将窗体置于前面 确保在所有子窗体上设置MdiParent属性 确保在父窗体上设置了IsMdiContainer属性 将子窗体的WindowState设置为Normal 使用Activate()激活表单并为其提供焦点 您还可以尝试利用父级的z顺序为孩子提供焦点: this.ActiveMdiChild.SendToBack(); Control.ControlCollection ct = ((MdiClient)this.ActiveM ...
  • 我想我发现了这个问题。 每次我们调整下一个嵌套窗口的大小时,内核堆栈都会增加,直到它没有enougth堆栈来调用wndproc并且我们停止接收消息。 更多细节可以在这里找到: http : //blogs.msdn.com/b/alejacma/archive/2008/11/20/controls-won-t-get-resized-once-the-nesting-hierarchy-of-windows -exceeds-A-一定深度-x64.aspx I think I found the prob ...
  • 嗯,我从来没有找到任何关于这个主题的权威文件。 这只是作为我的相当随机的内存转储尝试获取控件以“玩得很好”,当动画时,在一个被剥皮的窗口(具有位图背景的普通非客户区域),分层(以获得具有自定义非客户端的窗口)带阴影效果的边缘)或扩展的Aero Glass(通过DwmExtendFrameIntoClient)效果。 SetBKMode(... TRANSPARENT)只是确保文本渲染不会用当前的bk颜色填充文本的背景。 WS_EX_COMPOSITED导致窗口在父项失效时将父窗口和所有子窗口绘制到后台缓冲区 ...
  • 是的,将hbrBackground设置为NULL是避免实现无操作WM_ERASEBKGND处理程序的适当方法。 当您将WM_ERASEBKGND传递给DefWindowProc ,它会检查窗口类中的背景画笔。 如果有的话,用它填充脏区。 如果背景画笔为null,则它不执行任何操作并返回。 这与拥有自己的无操作WM_ERASEBKGND处理程序基本相同。 WM_ERASEBKGND处理程序的返回值会影响WM_PAINT调用BeginPaint时获取的PAINTSTRUCT的fErase字段。 WM_PAINT ...
  • 可能编译器足够聪明,可以为两个版本生成相同或非常相似的代码。 除非性能确实是您应用程序的关键因素,否则为了代码可读性,我会自动选择第二个版本。 Probably the compiler is smart enough to generate the same, or very similar code, for both versions. Unless performance is really a critical factor for your application, I would automa ...
  • 你只需通过擦除背景来处理WM_ERASEBKGND (使用FillRect()就可以)。 通过返回非零值,您只是告诉Windows,该消息已经被处理,不需要进一步的操作。 没有比这更正式的了。 You process WM_ERASEBKGND simply by erasing the background (using FillRect() is fine). By returning a non-zero value, you are simply telling Windows that this ...
  • 你关于'给予控制'回到viewController(VC)的评论没有意义,因为VC通常在runLoop回调中被阻塞,等待某事发生。 如果我理解你想要的东西,它就有机会在发生所有这些事情的同时获得处理VC的其他消息。 定义方法: { NSMutableArray *blocks; // ivar BOOL isCanceled; } typedef void (^block_t)(id input); -(void)performBlock:(id)result; 一次创建所有块或悠闲地执行, ...
  • 你应该改变一些事情: 当您处理WM_PAINT ,您应该调用BeginPaint来获取您的绘画的DC和其他信息,然后在完成后调用EndPaint 。 这为您提供了一个DC,可以将您的绘画限制在所需的剪裁区域,并防止闪烁。 case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); RECT rect; GetClientRect(hWnd, &rect); rect.bottom = 262; ...

相关文章

更多

最新问答

更多
  • 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
  • TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
  • 企业安全培训的各项内容
  • 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
  • NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
  • 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
  • 将多个行和可变行移动到列(moving multiple and variable rows to columns)
  • 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
  • Angular $资源不会改变方法(Angular $resource doesn't change method)
  • 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
  • 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
  • Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
  • 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)
  • 是否可以嵌套hazelcast IMaps?(Is it possible to nest hazelcast IMaps? And whick side effects can I expect? Is it a good Idea anyway?)
  • UIViewAnimationOptionRepeat在两个动画之间暂停(UIViewAnimationOptionRepeat pausing in between two animations)
  • 在x-kendo-template中使用Razor查询(Using Razor query within x-kendo-template)
  • 在BeautifulSoup中替换文本而不转义(Replace text without escaping in BeautifulSoup)
  • 如何在存根或模拟不存在的方法时配置Rspec以引发错误?(How can I configure Rspec to raise error when stubbing or mocking non-existing methods?)
  • asp用javascript(asp with javascript)
  • “%()s”在sql查询中的含义是什么?(What does “%()s” means in sql query?)
  • 如何为其编辑的内容提供自定义UITableViewCell上下文?(How to give a custom UITableViewCell context of what it is editing?)
  • c ++十进制到二进制,然后使用操作,然后回到十进制(c++ Decimal to binary, then use operation, then back to decimal)
  • 以编程方式创建视频?(Create videos programmatically?)
  • 无法在BeautifulSoup中正确解析数据(Unable to parse data correctly in BeautifulSoup)
  • webform和mvc的区别 知乎
  • 如何使用wadl2java生成REST服务模板,其中POST / PUT方法具有参数?(How do you generate REST service template with wadl2java where POST/PUT methods have parameters?)
  • 我无法理解我的travis构建有什么问题(I am having trouble understanding what is wrong with my travis build)
  • iOS9 Scope Bar出现在Search Bar后面或旁边(iOS9 Scope Bar appears either behind or beside Search Bar)
  • 为什么开机慢上面还显示;Inetrnet,Explorer
  • 有关调用远程WCF服务的超时问题(Timeout Question about Invoking a Remote WCF Service)