Почему "оператор bool ()" вызывается, когда я приводил к "long"? - PullRequest
2 голосов
/ 27 января 2010

У меня есть следующий класс:

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

Это скомпилировано с Microsoft SDK, который имеет следующие typedefs:

typedef long LONG_PTR;
typedef LONG_PTR LPARAM;

Телефонный код выполняет следующие действия:

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

Внезапно castResult is 1 - MyClass::operator bool() вызывается, он возвращает true, который преобразуется в 1. Поэтому вместо передачи адреса я передаю 1 в SendMessage(), что приводит к неопределенному поведению.

Но почему operator bool() вызывается в первую очередь?

Ответы [ 3 ]

11 голосов
/ 27 января 2010

Это одна из известных ловушек использования оператора bool, которая является вторичным толчком наследования Си. Вы бы определенно выиграли от чтения Safe Bool Idiom .

В общем, вы не предоставили никакого другого подходящего оператора приведения, и bool (к сожалению) считается хорошим источником для арифметического приведения.

5 голосов
/ 27 января 2010

operator bool является лучшим соответствием, потому что char* и void* не могут быть преобразованы в long без явного приведения, в отличие от bool:

long L1 = (void*)instance; // error
long L2 = (char*)instance; // error
long L3 = (bool)instance; // ok
2 голосов
/ 27 января 2010

Вы не можете неявно привести T* к длинному. Но вы можете бросить bool на долго.

Так что operator bool используется.

Вы должны определить operator LPARAM.

...