2017-02-10 28 views
2

У меня есть два класса A и B, каждый из которых имеет значение operator bool().Предотвращение преобразования двух объектов из двух классов в bool при выполнении: if (a! = B)

Недавно я наткнулся на ошибку, которая была вызвана:

A a; 
B b; 
if(a!=b) 
{ 
    //... 
} 

Этот код скомпилированный отлично под GCC 4.9.1 и преобразовываются а и Ь к BOOL перед сравнением.

Возможно ли определить что-то, что предотвратило бы это и вызвало бы ошибку компиляции, чтобы заставить программиста использовать явную функцию преобразования, предоставляемую A и B? Объявления A и B должны быть несвязанными, они находятся в разных заголовках.

+1

Вы можете перегрузить оператор ' ! = (A, B) 'или сделать ваши конверсии bool« явными » –

+3

Сделать преобразования для' bool' 'explicit'? Обычно это правильно, и контексты, такие как 'if (a)' все еще считаются *, контекстуально конвертируются в 'bool' * *. – BoBTFish

+0

, когда вы говорите «преобразование», вы имеете в виду «сравнение»? –

ответ

2

Очевидным способом является отметка operator bool() явно либо A, либо B (или оба). Это вызовет ошибку компилятора. Имейте в виду, что это может вызвать некоторые другие применения A или B - где такое неявное преобразование работает по назначению - также не компилируется. Существует бесплатный обед.

Целью кода является, по-видимому, сравнение объектов (или их элементов данных каким-либо образом). Если это так [то есть выбор дизайна для вас] было бы также стоит поставляя

bool operator!=(const A&, const B&);  // usage a != b 
    bool operator!=(const B&, const A&); // usage b != a 

В зависимости от типа, проходя один или более по значению может быть целесообразным. Альтернативой (например, если оба типа являются типами struct/class) заключается в осуществлении bool operator!=(const B &) const в качестве члена A и/или bool operator!=(const A &) const в качестве члена B.

Имейте в виду, что если operator!=() поставляется для двух типов, может также быть целесообразным предоставить другие операторы сравнения (например, ==). Это дизайнерское решение.

+0

Не могли бы вы объяснить о operator!()? Я не знал, что здесь задействован этот оператор, или это ошибка? – galinette

+0

Это хорошая идея, а не для того, чтобы сделать члены данных операторов сравнения операторами классов, поскольку они обычно не должны требовать доступа к частному члену. – SebNag

+0

Извините, - написал слишком быстро. 'operator bool'. Я исправлю. – Peter

1

Другим «взломом» было бы сделать преобразование bool явным, как уже упоминалось M.M, но это приводит к некоторым другим проблемам.

что-то вроде этого:

class A { // same for class B 
public: 
    explicit operator bool() { 
     // some code 
     return (true || false) && !(false && true); 
    } 
}; 

Теперь if(a==b) не будет компилировать больше, но if(a) и if(b) воли. HOWEVER, это приведет к некоторым другим проблемам, и неожиданное поведение, такое как if(a==true), также больше не будет компилироваться, так как a лидируется в целое число; Это также является причиной того, что в первую очередь составлял if(a==b).

Другим вариантом было бы удалить неявное преобразование INT: operator int() = delete;

Here пример вы можете играть Arround и посмотреть, что может произойти, если вы запутались с операторами преобразования ...