I have the following class:
class MyClass {
public:
MyClass( char* what ) : controlled( what ) {}
~MyClass() { delete[] controlled; }
operator char*() const { return controlled; }
operator void*() const { return controlled; }
operator bool() const { return controlled != 0; }
private:
char* controlled;
};
This is compiled with Microsoft SDK that has the following typedefs:
typedef long LONG_PTR;
typedef LONG_PTR LPARAM;
The calling code does the following:
MyClass instance( new char[1000] );
LPARAM castResult = (LPARAM)instance;
// Then we send message intending to pass the address of the buffer inside MyClass
::SendMessage( window, message, wParam, castResult );
Suddenly castResult
is 1
- 开发者_运维技巧MyClass::operator bool()
is invoked, it returns true
which is converted to 1
. So instead of passing the address I pass 1
into SendMessage()
which leads to undefined behaviour.
But why is operator bool()
invoked in the first place?
It's one of the known pitfalls of using operator bool, that is a aftershock of C inheritance. You'd definitively benefit from reading about the Safe Bool Idiom.
In general, you didn't provide any other matchable casting operator, and bool (unfortunately) is treated as a good source for arithmetic casting.
operator bool
is the best match, because char*
and void*
can't be converted to long
without an explicit cast, unlike bool
:
long L1 = (void*)instance; // error
long L2 = (char*)instance; // error
long L3 = (bool)instance; // ok
You cannot implicitly cast a T*
to long. But you can cast a bool to long.
So the operator bool
is used.
You have to define a operator LPARAM
.
精彩评论