Вы можете использовать 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
само по себе равно , а не a Derived
, иесли бы вы могли конвертировать Base&
в Derived&
без каких-либо проверок, вы могли бы сломать систему типов.
Тем не менее ... Я бы не стал этого делать вообще.Перегрузка operator!
для этой цели делает код менее читабельным, а простое написание *this
настолько идиоматично, что его скрытие сделает ваш код намного сложнее для понимания.Использование всего этого механизма шаблонов, чтобы избежать чего-то общего с C ++, кажется ошибочным.Если вы делаете что-то еще, прежде чем возвращать ссылку, это нормально, но это не кажется хорошей идеей.
Надеюсь, это поможет!