1

Динамическая привязка требует, чтобы виртуальная функция имела тот же список параметров в базовом классе и его производном классе. Это заставляет меня задаться вопросом, может ли оператор> динамически ограничиваться? Следующая демонстрация, похоже, доказывает, что она не может.Можно ли динамически связывать оператор>?

#include <iostream> 
using namespace std; 
struct B 
{ 
    B(int b = 0):m_b(b){} 
    virtual bool operator>(const B& rhs)const {cout << "B::operator>" << endl;return m_b > rhs.m_b;} 
    int m_b; 
}; 

struct D: public B 
{ 
    D(int b = 0, long d = 0):B(b),m_d(d){} 
    virtual bool operator>(const D& rhs)const {cout << "D::operator>" << endl; return m_d > rhs.m_d;} 
    long m_d; 
}; 
int main() 
{ 
    D d1(0,0),d2(1,-1); 
    B& b1(d1),b2(d2); 

    cout << (b1 > b2) << endl; 
    cout << "------------" << endl; 
    cout << (d1 > d2) << endl; 
    return 0; 
} 

выход:

B::operator> 
0 
------------ 
D::operator> 
1 
+3

Подписи не совпадают, вы не переопределяете базовую функцию (подсказка: используйте 'override' для проверки). Операторы - это просто функции и поэтому могут быть «виртуальными». – user657267

ответ

2
virtual bool operator>(const D& rhs)const { 
    cout << "D::operator>" << endl; 
    return m_d > rhs.m_d; 
} 
virtual bool operator>(const B& rhs)const override final { 
    if(D const*=dynamic_cast<D const*>(&rhs)) 
    return *this>*other; 
    return B::operator>(rhs); 
} 

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

Существует много способов сделать двойную отправку в C++, все они должны быть выполнены вручную.

+0

Как в стороне, 'override final' мешает другим производным классам пытаться перегрузить' operator> 'базового класса, вместо этого они должны переопределять' '' '' '' '' '' '' '' '' '', возможно с аналогичной проверкой и сделать то же самое «override final» при их переопределении при создании новой «виртуальной» перегрузки одного типа. Обратите внимание: если статический тип обоих аргументов известен на сайте вызова, он отправляет пролив в 'D const &' без динамического переноса. – Yakk

0

Вы должны использовать ту же сигнатуру в производный, чем в основании, так что он эффективно перекрывает основание:

struct D: public B 
{ 
    D(int b = 0, long d = 0):B(b),m_d(d){} 
    bool operator>(const B& rhs)const override { cout << "D::operator>" << endl; return m_d > static_cast<const D*>(&rhs)->m_d;} 
    long m_d; 
};