2016-08-10 7 views
24

У меня есть класс Base, ограничивающую explicit operator bool:Виртуальный оператор явного преобразования перекрывая

struct Base { 
    virtual explicit operator bool() const { 
     return true; 
    } 
}; 

И у меня есть подкласс Derived, определение operator bool:

struct Derived : Base { 
    operator bool() const override { 
     return false; 
    } 
}; 

Как вы можете заметить, Derived::operator bool явно не отмечено explicit, но отмечено override, поэтому я ожидал, что компилятор будет жаловаться. Однако, как gcc, так и clang, похоже, согласны с тем, что это действительно. Было ли мое ожидание необоснованным?

Кроме того, если я использую классы следующим образом, TakesBool(base) не компилируется (как и ожидалось), но TakesBool(derived) делает:

void TakesBool(bool b) {} 

int main() { 
    //Base base;  TakesBool(base); // compilation error (as expected) 
    Derived derived; TakesBool(derived); 
    return 0; 
} 

Это показывает, что Derived имеет (не- explicit) operator bool, который , однако, отмечается override без объявления virtual. Как это возможно?

+1

Относительно необходимости «виртуального» в производном классе, если базовый класс был помечен как «виртуальный», он подразумевается также для всех производных классов. Ключевое слово 'override' является скорее намеком для компилятора, поэтому вы не пытаетесь переопределить функцию, используя другую сигнатуру (например, объявляя функцию в производном классе, которая принимает разные аргументы, чем функция в базовом классе). Таким образом, эти ключевые слова не имеют отношения к вопросу. –

+1

Виртуальная отправка все еще происходит. 'Base * pbase = & производное; TakesBool ((bool) * pbase); 'будет вызывать' Derived :: operator bool'. Я думаю, что «явный» не считается частью сигнатуры функции, поэтому вам разрешено переопределять «явное» преобразование с помощью «неявного». Я не уверен, правильно ли это поведение. –

+0

Это похоже на функцию 'protected: virtual' в базовом классе с' public: override' в производном классе. Не проблема. –

ответ

17

Вы могли бы подумать, что в Derived Непостоянство explicitoperator bool не отменяет explicitoperator bool в Base, нет, это делает. explicit specifier не имеет значения, это не является частью сигнатуры функции.

От стандарта, §10.3/2 Virtual functions [class.virtual]:

(курсив мой)

If a virtual member function vf is declared in a class Base and in a class Derived , derived directly or indirectly from Base , a member function vf with the same name, parameter-type-list ([dcl.fct]), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf .

Так что компилятор будет жаловаться только тогда, когда имя, параметр-тип-лист, резюме квалификация или реф-Спецификатор функция не соответствует, явный спецификатор не будет рассмотрен.


Вы сказали, что «отмечен override без virtual декларации», обратите внимание, что virtual декларации функции члена в производном классе является излишней, это также virtual.

+2

Я исследовал, что возможно иметь базовый класс, который имеет как «явный оператор bool», так и «operator bool», и эти два обрабатываются по-разному. Вы знаете, что произойдет, если производный класс определяет 'operator bool() override'? Оправдывает ли он оба оператора 'bool'? – phimuemue

+0

@phimuemue Почему бы просто не попробовать? –

+0

@underscore_d Да, но меня интересует прежде всего ответ, основанный на стандарте. – phimuemue