2009-12-28 5 views
1

может кто-нибудь сказать мне, что отличает (*ptr).field и ptr->field? Я знаю, что это как-то соединить с статической и динамической связью, но я не знаю, что это такое. может кто-нибудь сказать мне differnet и дать мне пример?Различия в доступе пользователей

редактировать: , если у меня есть этот код:

Point p;  //point is a class that derive from class shape 
Shape *s=&p; 
       //there is a diffrence if i write: 

(*s).print(); //print is virtual func 
s->print(); // the answers will not be the same, why? 

TNX!

+0

Вы имели в виду '(* ptr) .field' или' * ptr.field'? Если вы действительно имели в виду '* ptr.поле ", то эти две формы просто не имеют ничего общего, что делает вопрос практически бессмысленным. – AnT

+0

i mean (* ptr) .field – aharon

+0

От вашего редактирования: ответ будет таким же. Смотри ниже. –

ответ

4

это не имеет ничего общего со статическими или динамическими связывая оба выражения будут возвращать значение ptr.field

ptr-> форма поля является сокращенным синтаксисом для доступа к члену непосредственно из указателя

UPDATE: мне пришло в голову, что ваша первоначальная цель не связывающей но связывание , если это действительно было то, что вы были с целью то есть статическое связывание и динамический связывание , которые имеют какое-то отношение к -> оператору see here

+1

Да, но сокращенно (* ptr) .fld, а не для * ptr.field. – ChrisInEdmonton

+1

Важно отметить, что они НЕ обязательно эквивалентны из-за возможности перегрузить оператор * и operator-> в C++! – HostileFork

+2

@Hostile Fork: Вот почему, в некоторых магазинах, сеансы проверки кода на C++ должны включать в себя машины электрошоковой терапии. –

2

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

Динамическое связывание выполняется путем размещения имени разделяемой библиотеки в исполняемом изображении. Фактическое связывание с библиотечными процедурами происходит не до тех пор, пока изображение не будет запущено, когда исполняемый файл и библиотека будут помещены в память. Преимущество динамической компоновки заключается в том, что несколько программ могут совместно использовать одну копию библиотеки.

Но это не связано с указателем указателя, о котором вы упоминали - на самом деле эти два выражения идентичны.

+1

Не совсем. Поле ptr-> совпадает с полем (* ptr) .field, а не с * ptr.field. – ChrisInEdmonton

0

Они оба одинаковы.
*ptr.field разыменовывает переменную ptr, а затем возвращает значение члена field.

Оператор -> является сокращенным обозначением для вышеуказанного.

+2

Собственно, '* ptr.field' оценивается как' * (ptr.field) ', а не' (* ptr) .field'. –

1

Это не имеет никакого отношения к связыванию.

ptr->fld 

просто сокращенная для

(*ptr).fld 

Это чисто синтаксический сахар;)

+0

В частности, см. П. 5.2.5.3 стандарта C++. – outis

+1

§ 5.2.5 3 Если E1 имеет тип «указатель на класс X», то выражение E1-> E2 преобразуется в эквивалентную форму (* (E1)). E2; в оставшейся части 5.2.5 будет рассмотрен только первый вариант (точка). – outis

+0

@outis: часть, которую вы цитируете, описывает поведение * встроенного * оператора '->'. Не забывайте, что '->' в C++ не обязательно относится к встроенному оператору. Он также может быть перегружен пользователем. ОП не сказал, что 'ptr' имеет тип необработанного указателя. – AnT

2

Я предполагаю, что вы имели в виду *ptr.field(*ptr).field.

Поскольку учитываются только встроенные операторы, между ними нет никакой разницы. И нет, это не имеет ничего общего с «статическими» или «динамическими» связями, что подразумевается под этими терминами.

только разность потенциалов между ними состоит в том, что в варианте ptr->field-> является Перегружаемым оператором в C++, в то время как в варианте (*ptr).field только * является Перегружаемым, в то время как . нет.

Кроме того, некоторые различия между этими двумя методами доступа членов существовали в очень архаичных версиях языка C (CRM C), но я сомневаюсь, что кто-то заботится о них сегодня.

1

До тех пор, пока ptr является указателем, они эквивалентны в правильном заключении в скобки (как говорили другие). Если ptr является объектом, а не указателем, они могут отличаться в зависимости от определений для operator* и operator-> (если есть) из класса объекта или предков.

+0

ok, если у меня есть этот код: Point p; // point - это класс, который получается из формы класса Shape * s = & p; есть diffrence, если я пишу (* s) .print(); // print - виртуальный func - s-> print(); ответы не совпадают, так почему? – aharon

7

Это не имеет никакого отношения к статическому или динамическому связыванию.

См. C++'s operator precedence. . имеет более низкий приоритет, чем *, так что на самом деле разница между *ptr.fld и ptr->fld. Например, следующий код демонстрирует:

#include <iostream> 

struct foo { 
    int f; 
}; 

int main() { 
    struct foo *p = new struct foo; 
    p->f = 42; 
    std::cout << p->f << std::endl; 
    std::cout << (*p).f << std::endl; 
    // The following will not compile 
    // std::cout << *p.f << std::endl; 
} 

Как Джон Knoeller указывает, ptr->fld является синтаксически (*(ptr)).fld, но это не то же самое, как *ptr.fld, который будет на самом деле оценить в *(ptr.fld), вероятно, не то, что вы хотите.

Вы должны использовать ptr->fld, если у вас есть указатель на структуру и хотите получить доступ к содержащемуся в ней поле. (*(ptr)).fld означает то же самое, но не такое аккуратное. Вы должны использовать *strct.fld, если у вас есть структура, а не указатель на структуру, которая содержит поле (fld), которое является указателем, который вы хотите разыменовать. Пример ptr->fld показан выше. Случай *strct.fld может использоваться со следующей структурой:

struct foo { 
    int *fld; 
} 

struct foo f; 
f.fld = new int; 
*f.fld = 42; 
+0

Как указывалось outis, поле ptr-> на самом деле является синтаксическим сахаром для поля (* (ptr)), а не для поля (* ptr). По электронной почте Ой. Исправлена. – ChrisInEdmonton

+0

Поскольку 'ptr' является идентификатором,' (* ptr) .field' в порядке. Тем не менее, хорошо отметить общий случай. – outis

+0

OP подтвердил, что он на самом деле означал '(* ptr) .field'. Я редактировал вопрос. – AnT

1

формы -> это просто сокращение для де-refrencing указателя и доступа к члену.

(*ptr).field; 
// Equiv to 
ptr->field; 

Одна хорошая причина для использования -> в том, что, когда вы следуете цепи:

int x = (*(*(*(*ptr).field1).field2).field3).field4; 
// Equiv to 
int y = ptr->field1->field2->field3->field4; 

Второй становится гораздо более удобным для чтения.

Что касается второй части вашего вопроса.
Мне очень легко просто нарисовать пример.

#include <iostream> 

class Shape 
{ 
    public: virtual ~Shape()  {} 
       virtual void Print() {std::cout << "Shape\n";} 
}; 
class Point: public Shape 
{ 
    public: virtual void Print() {std::cout << "Point\n";} 
}; 

int main() 
{ 
    Point p; 
    Shape* s = &p; 

    s->Print(); 
    (*s).Print(); 
} 

> vi x.cpp 
> g++ x.cpp 
> ./a.exe 
Point 
Point 

Как вы можете видеть, результат одинаковый в обеих ситуациях.

При вызове метода с помощью указателя или ссылки будет вызываться механизм виртуального вызова. Оператор звезды (оператор блокировки AKA) возвращает ссылку на объект (он фактически не отменяет ссылку на объект). Поэтому, когда он используется для вызова метода, вызывается механизм виртуального вызова и вызывается наиболее производная версия метода.

+0

ОК, танки, хотя мой DR. сказал, что есть разные, но я не могу вспомнить, что ... – aharon

+0

Нет никакой разницы между (* ptr) -> f1 и ptr-> f1. Это определяется стандартом. Если мы перейдем к виртуальным функциям. Существуют ситуации, когда механизм виртального вызова не будет использоваться, но это не один из них. –

+0

, так что в случае, если механизм виртального вызова не будет использоваться? – aharon