2016-08-03 2 views
1

У меня проблема, но я не знаю, правильно ли я ее решил или есть более правильные способы.Листинг базы данных const для производных

Теперь у меня есть два класса (и один наследует от другого):

class Data_Base 
{ 
... 
} 

class Data_Error : public Data_Base 
{ 
... 
} 

В настоящее время, в перегрузке оператора равенства, я должен бросить константную ссылку на базовый объект к производным объект снова, чтобы проверить его участников. В настоящее время я делаю это:

bool Data_Error::operator==(const Data_Base &other) const 
{ 
    if (Data_Base::operator !=(other)) 
     return false; 

    const Data_Error &other_cast = (const Data_Error &)other; 

    ... More tests on other_cast ... 
} 

Теперь, нет никакой возможности, что в литейном момент переменная other это нечто иное, чем Data_Error, так как Data_Base== оператора (и оператора !=, так как она реализуется как отрицание ==) также проверяет тип производного объекта, поэтому он достигает этой строки только в том случае, если тип верен.

Теперь есть ли какие-либо проблемы с этим? Есть ли «более правильное» решение?

Я работаю с Qt (5.7), так есть ли решение «больше QTish»?

+0

Почему вы сравниваете 'Data_Error' с потомком Data_Base? Какое значение имеет значение для сравнения типов в разных ветвях в иерархии? Просто придерживайтесь 'bool Data_Error :: operator == (const Data_Error & other) const', я говорю. – StoryTeller

+0

@StoryTeller Поскольку, когда у меня есть список базовых типов, я хочу выполнить итерацию на нем, чтобы проверить, соответствуют ли некоторые из элементов этому. Я просто вызываю == для каждого элемента; в функции я проверяю, является ли тип одинаковым, иначе они не равны. Но для этой цели тип другой должен быть базовым, иначе программа не знает, как сравнивать две разные ветви. – frarugi87

+0

Является ли ваш 'operator ==' виртуальным? Если это не так, оно не будет работать так, как вы ожидаете. – StoryTeller

ответ

1

Следует избегать отливок в стиле C. Вы можете найти, почему here. Вы должны использовать статический бросок вместо:

const Data_Error &other_cast = static_cast<const Data_Error &>(other); 

Или динамическое приведение, чтобы проверить во время выполнения другой эффективно типа Data_Error:

const Data_Error &other_cast = dynamic_cast<const Data_Error &>(other); 
+2

Для этих целей более динамичный приведение более подходит – LmTinyToon

+0

Я сначала добавил его, но не знал о поведении со ссылками. Но вы правы, я его прочитал – wasthishelpful

+0

Итак, решение 'dynamic_cast' лучше? Если да, то что, если бросок не сработает? Выбрасывает ли это исключение или устанавливает 'other_cast' в' nullptr'? – frarugi87

1

Правильный путь заключается в использовании dynamic_cast на указатели, потому что это просто возвращает null, если объект не является правильным производным типом. Ваш пример станет следующим:

bool Data_Error::operator==(const Data_Base &other) const 
{ 
    if (Data_Base::operator !=(other)) 
     return false; 

    const Data_Error *other_cast = dynamic_cast<const Data_Error *>(&other); 
    if (other_cast == nullptr) { // not the correct type 
     return false; 
    } 

    ... More tests on *other_cast ... 
} 
+0

Это влияет на «константу» других? – frarugi87

+0

Зачем вам использовать dynamic_cast для этого? Если вы знаете тип уже, вы можете static_cast его. «нет никакой возможности, что в момент броска другая переменная - это нечто иное, чем Data_Error» – xaxxon

+0

@ frarugi87: нет, это преобразование const ref в указатель на const. Таким образом, * constness * сохраняется здесь. –

Смежные вопросы