Вопрос

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

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

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?

Спасибо!

Это было полезно?

Решение

Это не имеет ничего общего со статическим или динамичным связыванием обоих выражений вернет значение Ptr.field

форма ptr->field — это сокращенный синтаксис для доступа к элементу непосредственно из указателя.

ОБНОВЛЯТЬ:мне пришло в голову, что вашим первоначальным намерением было не связывание, а обязательность если это действительно было то, к чему вы стремились, то есть статическая привязка и динамическая привязкакоторые имеют некоторое отношение к оператору -> глянь сюда

Другие советы

Это не имеет ничего общего со статическим или динамическим связыванием.

Видеть Приоритет операторов C++. имеет более низкий приоритет, чем *, так что на самом деле есть большая разница между *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;
}

Как отмечает Джон Кноллер, 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;

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

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

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

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

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

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

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

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

ptr->fld 

это просто сокращение от

(*ptr).fld

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

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

Форма -> — это просто сокращение для отмены ссылки на указатель и доступа к элементу.

(*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) возвращает ссылку на объект (фактически он не отменяет ссылку на объект).Поэтому, когда он используется для вызова метода, будет вызван механизм виртуального вызова и вызвана наиболее производная версия метода.

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

А -> оператор является сокращенной записью вышеизложенного.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top