Почему оператор-> может быть перегружен вручную?
Не имеет смысла, если p->m
был просто синтаксическим сахаром для (*p).m
? По существу, каждый operator->
, который я когда-либо писал, мог быть реализован следующим образом:
Foo::Foo* operator->()
{
return &**this;
}
Есть ли случай, когда я хотел бы, чтобы p->m
означал что-то еще, чем (*p).m
?
Ответы
Ответ 1
operator->()
имеет странное различие , неявно вызываемое повторно, в то время как тип возвращаемого значения позволяет ему. Самый ясный способ показать это с кодом:
struct X {
int foo;
};
struct Y {
X x;
X* operator->() { return &x; }
};
struct Z {
Y y;
Y& operator->() { return y; }
};
Z z;
z->foo = 42; // Works! Calls both!
Я вспоминаю случай, когда это поведение было необходимо для того, чтобы объект мог вести себя как прокси для другого объекта в контексте с интеллектуальным указателем, хотя я не могу запомнить детали. Я помню, что я мог только заставить поведение работать, как я предполагал использовать синтаксис a->b
, используя этот странный частный случай; Я не мог найти способ заставить (*a).b
работать аналогичным образом.
Не уверен, что это отвечает на ваш вопрос; я действительно говорю: "Хороший вопрос, но это даже странно!"
Ответ 2
Один пример использования может быть, когда вы создаете DSL внутри С++, в соответствии с Boost Karma (хотя это не кажется перегрузить ->
в свою библиотеку), где вы полностью меняете смысл традиционных операторов С++. Является ли это хорошей идеей, безусловно, для обсуждения.
Ответ 3
Регулярные указатели предлагают p->m
и (*p).m
, причем p->m
является наиболее распространенным. Если вы допустили только перегрузку одного из них, это будет несовместимо с типом по умолчанию. Что касается того, почему не позволить компилятору переписать его, простой ответ заключается в том, что иногда вы не хотите, чтобы operator- > возвращал T *, где оператор * возвращает T &. Позволяя им перегружать отдельно, вы можете комбинировать комбинации, о которых вы не можете думать. Но было бы глупо отрицать это, просто потому, что мы не можем сейчас думать о какой-либо причине, чтобы изменить его. Как бы то ни было, у вас мог бы быть класс int128 и оператор перегрузки + = для обозначения возведения в степень вместо этого, если вы этого хотели.
Ответ 4
Возможно, вы захотите выполнить некоторые другие операции, такие как увеличение переменной (подсчет доступа) или даже некоторые проверки безопасности и т.д. С другой стороны, мне никогда не нужно было перегружать оператор- > ...
Ответ 5
Я думаю, что он использовался для shared_ptr < > in boost (например). Это делает их "похожими на обычные указатели", хотя они являются особыми указателями (ссылка на счет afaik).