2010-10-05 3 views
2

Можно создать дубликат:
Why does C have a distinction between -> and . ?Зачем писать -> а не.?

Какова реальная причина для программиста, чтобы различать . и -> при доступе к члену объекта?

void foo(Point &p) { 
    p.x ; 
    p->y; // syntax error 
} 

void foo(Point *p) { 
    p.x ; // syntax error 
    p->y; 
} 

То есть, так или иначе, они оба относятся к объекта, р.

  • Почему я должен постоянно проверять, что такое p? Не может понять компилятор?

  • Почему они не позволили ему принять . синтаксис для обоих? Это было бы хорошо для объектов стека тоже.

И если это связано с C-традиции,

  • Почему они не позволяют одновременно . и -> аксессоров?

Более 15 лет я всегда смиренно рассматривал ошибки компилятора как свою ошибку!

+0

Возможный дубликат http://stackoverflow.com/questions/1813865/why-does-c-have-a-distinction-between-and/1813883#1813883. Хотя это касается C, многие ответы касаются проблем C++. –

+0

Это то, что есть. Привыкайте к нему или используйте другой язык. Если Kernighan или Ritchie не начали публиковать сообщения в StackOverflow, вы вряд ли получите хороший ответ. –

+3

Я вижу вашу точку зрения, но я думаю, что идея «ошибки компилятора, являющаяся моей ошибкой», немного упущена. * Ошибки сами по себе - это хорошо, что очевидно, когда вы сравниваете ошибки с молчаливым сбоем компиляции. Это не сообщения об ошибках, но неспособность принять и скомпилировать этот код, который раздражает. Правильно? Небольшая точка, но я надеюсь, что это прояснит вопрос: почему компилятор (эквивалент: спецификация языка C++) не позволяет это выражение? Это то, что вы сказали в своих пунктах. – LarsH

ответ

8

Потому что p->d фактически означает (*p).d. Это делает разыменование, а затем доступ к члену. Ссылки ведут себя как объекты, поэтому им не нужны разыменования (они также являются функцией C++, а указатель унаследован от C); он был сохранен таким образом для обратной совместимости.

C++ полна несоответствий, подобных этому, но обычно нет лучшего выбора для добавления новых функций. и поддерживают старый код. Переписывание старого кода не является вариантом.

+0

Теперь imageine d является следующим связанным списком. '(* (* (* (* p) .next) .next) .next) .next' совпадает с' p-> next-> next-> next-> next' –

2

Потому что указатели и ссылки разные, и обрабатываются по-разному?

Я ценю визуальную разницу, когда читаю код.

6

Потому что у вас может быть умный указатель. В этом случае вы можете получить доступ к элементам интеллектуального указателя, используя . и элементы реального объекта, используя ->.

+8

Разве это не так? вокруг - умные указатели, использующие эту функцию, а не функцию, присутствующую там, так что умные указатели могут существовать ... – naumcho

+2

Это может быть и то, и другое. C явно различался между '.' и' -> 'до того, как были такие вещи, как умные указатели. Но C++ * могли * в принципе решили объединить их, как предлагал OP, позволяя использовать любой синтаксис. Но тогда было бы невозможно реализовать интеллектуальные указатели – jalf

+0

@ user779 Я бы сказал, что у вас есть точка :) – AraK

4

Это не то же самое.

. есть, когда у вас есть реальный объект.
-> - это когда у вас есть указатель на объект.

Оператор . не может быть перегружен, а оператор -> может быть перегружен.

+0

Вопрос OP заключается не в том, когда использовать что, но почему существуют две разные формы синтаксиса. – jalf

2

Рассмотрим следующий фрагмент кода:

x.myInt = 3; 
cout << (int)&x <<< endl; 

Что мы здесь печать? Адрес указателя или адрес объекта? Я приветствую разницу между . и ->, потому что это дает вам больше контекста для кода.

С предлагаемым изменением мы не знали бы разницы, не глядя на то, что тип x.

+0

Да, это пример того, о чем я говорил в своем ответе. – LarsH

3

В теории, по крайней мере, на языке C, этот язык мог быть разработан для этого. D (на одном примере) делает именно то, о чем вы просите.

В C++, то может быть большой уродливее - это вполне возможно x->y и x.y в оба действительны, но означают сплошь различные вещи (то есть, умный указатель, который перегружает operator->):

#include <iostream> 

class P { 
    class inner { 
    public: 
     inner() : x(1) {} 
     int x; 
    } i; 
public: 
    int x; 


    P() :x(0) {} 

    inner *operator->() { return &i; } 
}; 

int main() { 
    P p; 
    std::cout << p.x << "\t" << p->x << "\n"; 
    return 0; 
} 
+0

Использование отдельных разделителей в C является * хорошей конструктивной особенностью *, чего, к сожалению, нет в C#. В C, в 'foo = bar; foo-> boz = 3; 'второй оператор не изменяет' foo', но делает modifiy 'bar-> boz'. Напротив, в 'foo = bar; Foo.boz = 3; ', второй оператор модифицирует' foo', но не изменяет 'bar.boz'. Я хочу, чтобы C# и .NET допускали, чтобы члены, не являющиеся полями, объявлялись с использованием того или иного оператора, с '->' подразумевая, что 'this' будет передаваться по значению и' .', подразумевая pass by ref. Классы полей будут использовать '->', а поля struct - '.'. – supercat

3

Умные указатели: они могут иметь оба члена и указывать на некоторые другие значения. Например:

boost::smart_ptr<someclass> x(new someclass()) 
x->some_method(); 
x.reset(); 
2

Это вопрос удобства: p-> Foo такое же, как (* р) .foo

Это как спрашивать, почему у ++ или оператор + =, когда вы можете выражают ту же логику с помощью простых операторов + и =.

+0

Теперь imageine foo является следующим связанным списком. (* (* (* (* p) .next) .next) .next) .next то же самое, что и p-> next-> next-> next-> next –

0

Я могу думать об одной причине: чем сложнее сопоставление между тем, что написал разработчик, но и тем, что они действительно хотели, тем труднее выяснить, что они на самом деле имели в виду, когда есть ошибка типа или синтаксиса.

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