为什么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 function
和non-member function
有什么区别吗?谢谢你的帮助!
I remeber
C++ Primer
tells usoperator<
should benon-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 toFloat
?)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 ofnon-member function
?- Why
C++ Primer
suggestsbinary operator
s benon-member function
?- Is there any other case that
member function
andnon-member function
make difference?Thanks for helping!
原文:https://stackoverflow.com/questions/12047174
最满意答案
我想我发现了这个问题。 每次我们调整下一个嵌套窗口的大小时,内核堆栈都会增加,直到它没有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 ...
-
SetWindowHookEx在嵌套窗口中阻止WM_ERASEBKGND(SetWindowHookEx blocks WM_ERASEBKGND in nested window)[2023-06-15]
我想我发现了这个问题。 每次我们调整下一个嵌套窗口的大小时,内核堆栈都会增加,直到它没有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 ...
-
擦除窗口背景win32API(Erase window background win32API)[2022-04-01]
你只需通过擦除背景来处理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 ... -
避免嵌套块(Avoiding Nested Blocks)[2023-04-30]
你关于'给予控制'回到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; ...