2015-02-06 3 views
1

Fellas, почему этот код не работает?Оператор шаблона, возвращающий ссылку на абстрактный класс

template <typename t> 
class Abstract 
{ 
public: 
    ~Abstract(){} 
    virtual Abstract<t>& operator +(Abstract<t>&) = 0; 
}; 

template <typename t> 
class Not_Abstract : public Abstract 
{ 
t* tab; //let Not_Abstract store an array of objects of type t, whatever 
public: 
    ~Not_Abstract(){ delete[] tab; } 
    Not_Abstract<t>& operator +(Not_Abstact<t>&); 
}; 

Я, хотя это потому, что ссылка является указателем, тогда я не знаю, оба определения оператора эквивалентны; но они кажутся отдельными функциями. Есть ли что-то, что можно сделать, чтобы сохранить виртуальный оператор в «Абстрактном» и все еще работать с кодом?

+3

Компилятор должен дать ясную ошибку. Изменить: Clang дает * ошибку: ожидаемое имя класса * в строке декларации 'Not_Abstract'. Это не кристально понятно, но 'Abstract' - это шаблон, а не класс. Кроме того, простая опечатка - явная ошибка, и она компилируется в противном случае. Не знаете, в чем проблема. – chris

+0

Мы не _Fellas_ мы * кодеры *. Совершенно разные. :) – ForceBru

+0

@chris Вы можете явно указать его: они должны наследовать от 'Abstract '. – Angew

ответ

1

Для того, чтобы функция в производном классе будет реализация функции виртуального члена в базовом классе, он должен быть объявлен таким образом, что аргумент типа остается неизменным:

Not_Abstract<t>& operator +(Abstact<t>&); 

Если вы хотите сделать убедитесь, что вы имеете дело с экземпляром Non_Abstract в качестве RHS оператора, вы должны выполнить dynamic_cast при реализации функции.

template <typename t> 
Not_Abstract<t>& Not_Abstract<T>::operator +(Abstact<t>& rhsBase) 
{ 
    Not_Abstract<t>& rhs = dynamic_cast<Not_Abstract<t>&>(rhsBase); 
    // ... Now work with a Not_Abstract object 
    // .... 

} 

Если rhsBase не может быть приведен к Not_Abstract<t>&, dynamic_cast бросит std::bad_cast исключение. Ваш код должен быть готов к тому, чтобы это исключение было брошено.

3

both operator's definitions are equivalent

Нет, они не являются. У одного есть параметр Abstract&, другой параметр Not_Abstract&. Для переопределения типы параметров должны совпадать, так что переопределение может быть вызвано так же, как и функция, которую он переопределяет.

Is there anything that can be done to retain virtual operator in "Abstract" and still have the code functioning?

Процентовка будет принимать Abstract&, и делать правильные вещи или нет это называется с Non_Abstract.

+0

Итак, результат должен совпадать, но не аргумент? Если я изменил аргумент на ссылку на мой абстрактный класс, у меня не будет доступа к его частной части, так как он не имеет. – Jules

+0

Подождите, или наоборот? xD – Jules

+1

@Jules: результат может быть ковариантным - то есть переопределение может возвращать более производный тип - так что это нормально. Параметр должен соответствовать - виртуальные функции должны быть вызваны через базовый класс, поэтому их необходимо вызывать любым типом, полученным из 'Abstract', а не только' Not_Abstract'. Для обработки параметра как 'Non_Abstract' вам понадобятся либо более виртуальные функции (возможно, что-то в соответствии с шаблоном Visitor), либо' dynamic_cast'. –

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