2012-02-13 8 views
2

Для некоторых синтаксического сахара, я хочу вернуть ссылку на this, но когда наследуется, функция должна возвращать тип дочернего класса:Возвращение ссылки на это и наследовании

class base { 
    T &operator!() { return *this; } 
}; 
base b; b = !b; 

class child : public base {}; 
child c; c = !c; 

Из-за оператором, я не может просто вернуть указатель и dynamic_cast, он должен быть ссылкой.

Возможно ли это? Использование не decltype(*this) для T не работает, ни делает auto f()->decltype(*this), из-за this (хотя я не понимаю, почему в авто-случае)

В Scala вы можете написать что-то вроде:

template<typename T> class base { 
    T &f() { return *this; } 
}; 
class child : public base<child> {}; 

Но мой g ++ не согласится с этим (не уверен, что это ошибка или просто нет в спецификации?)

Конечно, есть явный способ, но мне интересно, можно ли этого избежать с помощью возможностей C++ 11?

class child : public base { 
    child &operator!() { base::operator!(); return *this } 
}; 
+0

Пожалуйста, не переопределяйте операторов так, чтобы они меняли свои фундаментальные значения. Это очень плохая идея и приведет к путанице и ошибкам. –

+0

В этом случае это вещь DSL, я использую && на самом деле, и даже если она не возвращает bool, она семантически означает «и» – pascal

ответ

1

Вы можете использовать CRTP, чтобы это сделать, если вы позволили сделать base шаблон:

template <typename Derived> class Base { 
protected: 
    Derived& refToThis() { 
     return *static_cast<Derived*>(this); 
    } 
}; 

Примечание дополнительный бросок здесь. Причина это работает в том, что если у вас есть класс, как этот:

class Subclass: public Base<Subclass> { 
    /* ... */ 
}; 

Затем, если вы звоните refToThis внутри этого класса, он будет вызывать версию базового класса. Так как класс наследует от Base<Subclass>, то экземпляр шаблона для refToThis будет

Subclass& refToThis() { 
     return *static_cast<Subclass*>(this); 
    } 

Этот код является безопасным, так как this указатель действительно указывают на Subclass объекта. Более того, static_cast гарантирует, что при выполнении компиляции сбой не выполняется, если производный класс не наследует от Base, так как тип указателя не будет конвертируемым.

Причина, по которой бросок необходимо в том, что если вы просто сказать

template <typename Derived> class Base { 
protected: 
    Derived& refToThis() { 
     return *this; 
    } 
}; 

Тогда есть ошибка типа в программе, так как Base сама по себе неDerived, и если вы может преобразовать Base& в Derived& без каких-либо проверок, которые вы могли бы разбить систему типов.

Это сказало ... Я бы этого не сделал. Перегрузка operator! для этой цели делает код менее читаемым, и просто запись *this настолько идиоматично, что скрыть его сделает ваш код намного сложнее понять. Использование всего этого шаблонного механизма, чтобы избежать чего-то, что является обычным C++, кажется ошибочным. Если вы делаете что-то еще, прежде чем возвращать ссылку, это нормально, но это просто не кажется хорошей идеей.

Надеюсь, это поможет!

+0

спасибо, в моем коде было некоторое вмешательство, вызвавшее ошибку в подклассе class : public Base 'line, я боялся, что это невозможно в C++. – pascal

0

Пожалуйста, не делайте этого. Уже есть способ сделать это на языке, *whatever_pointer_you_want_to_use_this_crazy_operator_upon.Создание нового способа сделать что-то на этом языке просто смутит ваших будущих сопровождающих. Есть ли что-то еще, которое вы на самом деле пытаетесь достичь здесь?

+0

То, что я действительно хочу сделать, это 'a << b << c << d', где оператор' << 'определен в базовом классе и унаследован, однако мне нужен подтип с левой стороны, в отличие от ostream – pascal

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

  • Нет связанных вопросов^_^