Действительно ли это - хорошая идея указателям определения типа?

Ваше событие сброса вызвано span, а не содержащим div. Таким образом, перетаскиваемый элемент добавляется к промежутку, на который он перетаскивается.

Вы можете предотвратить это, изменив строку

ev.target.appendChild(document.getElementById(data)); на ev.target.closest('div').appendChild(document.getElementById(data));

68
задан Jonathan Leffler 8 November 2014 в 17:50
поделиться

11 ответов

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

По сути, если ваш код никогда не будет разыменовывать указатель, и вы просто передаете его функциям API (иногда по ссылке), то typedef не только уменьшает количество * s в вашем коде, но также предлагает программисту не вмешиваться в указатель.

Это также упрощает изменение API в будущем, если возникнет такая необходимость. Например, если вы перейдете на использование идентификатора, а не указателя (или наоборот), существующий код не сломается, потому что указатель никогда не должен был быть разыменован в первую очередь.

100
ответ дан TechnicallyTrue 24 November 2019 в 13:59
поделиться

Некоторое время назад я бы ответил «нет» на этот вопрос. Теперь, с появлением умных указателей, указатели уже не всегда обозначаются звездочкой «*». Так что нет ничего очевидного в том, что тип является указателем или нет.

Итак, теперь я бы сказал: нормально указывать указатели, если ясно, что это «тип указателя». Это означает, что вы должны использовать префикс / суффикс специально для него. Нет, например, "p" не является достаточным префиксом. Я бы, наверное, пошел с "ptr".

0
ответ дан Benoît 24 November 2019 в 13:59
поделиться

Цель с помощью typedef - скрыть детали реализации, но определение типа свойства указателя скрывает слишком много и делает код сложнее читать / понимать. Поэтому, пожалуйста, не делайте этого.


Если вы хотите скрыть детали реализации (что часто бывает полезно), не скрывайте часть указателя. Возьмем, к примеру, прототип для стандартного интерфейса FILE :

FILE *fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, FILE *stream);

здесь fopen возвращает указатель на некоторую структуру FILE (реализация которой вам неизвестна) детали для). Может быть, FILE не очень хороший пример, потому что в этом случае он мог бы работать с некоторым типом pFILE, который скрывал тот факт, что он является указателем.

pFILE fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, pFILE stream);

Однако это сработало бы только потому, что вы никогда не возитесь с содержанием, на которое указывает непосредственно. В тот момент, когда вы набираете указатель на то, что вы в некоторых местах модифицируете код, мне становится очень трудно читать.

1
ответ дан hlovdal 24 November 2019 в 13:59
поделиться

Win32 API делает это практически со всеми структурами (если не со всеми)

POINT => *LPPOINT
WNDCLASSEX => *LPWNDCLASSEX
RECT => *LPRECT
PRINT_INFO_2 => *LPPRINT_INFO_2

Хорошо, как это является последовательным, но, на мой взгляд, это не добавляет элегантности.

1
ответ дан dreamlax 24 November 2019 в 13:59
поделиться

Typedef используется для того, чтобы сделать код более читабельным, но указатель типа typedef увеличит путаницу. Лучше избегать указателей typedef.

4
ответ дан Chand 24 November 2019 в 13:59
поделиться

Это вопрос стиля. Этот вид кода очень часто встречается в заголовочных файлах Windows. Хотя они, как правило, предпочитают все заглавные буквы версии вместо префикса строчными буквами p.

Лично я избегаю такого использования typedef. Гораздо понятнее, чтобы пользователь явно сказал, что хочет Foo *, чем PFoo. Typedef лучше всего подходят для того, чтобы сделать STL читабельным:)

typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;
5
ответ дан JaredPar 24 November 2019 в 13:59
поделиться

Это может помочь вам избежать некоторых ошибок. Например, в следующем коде:

int* pointer1, pointer2;

pointer2 не является int * , это просто int . Но с typedefs этого не произойдет:

typedef int* pInt;
pInt pointer1, pointer2;

Они оба int * сейчас.

14
ответ дан Sad Developer 24 November 2019 в 13:59
поделиться

Не в моем опыте. Скрытие « * » затрудняет чтение кода.

70
ответ дан sigjuice 24 November 2019 в 13:59
поделиться

Единственный раз, когда я использую указатель внутри typedef, это когда имею дело с указателями на функции:

typedef void (*SigCatcher(int, void (*)(int)))(int);

typedef void (*SigCatcher)(int);

SigCatcher old = signal(SIGINT, SIG_IGN);

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


Вычеркнутое объявление является правильным типом для указателя на функцию signal () , а не для ловушки сигналов. Это можно сделать более понятным (используя исправленный тип SigCatcher выше), написав:
  typedef SigCatcher (* SignalFunction) (int, SigCatcher);

Или, чтобы объявить функцию signal () :

  extern сигнал SigCatcher (int, SigCatcher);

То есть SignalFunction - это указатель на функцию, которая принимает два аргумента ( int и SigCatcher ) и возвращает SigCatcher . А сама функция signal () является функцией, которая принимает два аргумента ( int и SigCatcher ) и возвращает SigCatcher .

28
ответ дан Jonathan Leffler 24 November 2019 в 13:59
поделиться

Это (как и многие ответы) зависит.

В Си это очень часто, так как вы пытаетесь скрыть, что объект является указателем. Вы пытаетесь предположить, что это объект, которым манипулируют все ваши функции (мы знаем, что это указатель внизу, но он представляет объект, которым вы манипулируете).

MYDB   db = MYDBcreateDB("Plop://djdjdjjdjd");

MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);

Под MYDB, вероятно, указатель на какой-то объект.

В C ++ это больше не требуется.
Главным образом потому, что мы можем передавать вещи по ссылке, а методы включаются в объявление класса.

MyDB   db("Plop://djdjdjjdjd");

db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db);   // This time we can call be reference.
db.destroyDB();     // Or let the destructor handle it.
5
ответ дан Martin York 24 November 2019 в 13:59
поделиться
-

Если вы это сделаете, вы не сможете создать контейнеры STL Const PsoMeStuct, поскольку компилятор считается:

list<const pSomeStruct> structs;

как

list<SomeStruct * const> structs;

, который не является законным контейнером STL, поскольку Элементы не являются назначаемыми.

См. В этом вопрос .

3
ответ дан 24 November 2019 в 13:59
поделиться