pointer-to-class-object to pointer-to-long
может ли считаться следующая запись корректной.
проверял - работает, но, возможно, - случайность.
class CLASS{...};
CLASS oclass_1;
CLASS oclass_2;
long* lpmas[2] = {
(long*) &C1,
(long*) &C2
};
...
CLASS* pclass_1 = lpmas[0];
pclass_1 -> ...;
вопрос можно перефразировать.
является ли указатель на объект класса "простым"
32-битным числом (в 32-платформах) или к нему компилятор
что-нибудь присобачивает (типа как 2 байта перед указателем на область
памяти, выделенной оператором new) и можно ли его подобным образом конвертировать?
спасибо.
может ли считаться следующая запись корректной.
[/QUOTE]
С точки зрения компилятора - да, с одним замечанием:
CLASS* pclass_1 = (CLASS*)lpmas[0];
С точки зрения концепции ООП - нет.
[QUOTE=smax13]
вопрос можно перефразировать.
является ли указатель на объект класса "простым"
32-битным числом (в 32-платформах)
[/QUOTE]
Да
И вместо long* здесь вполне может быть void*.
[QUOTE=smax13]
можно ли его подобным образом конвертировать?
[/QUOTE]
Нежелательно, т.к. в данном случае нарушается типовая безопасность.
подобные преобразования вполне безопасны. я так понял?
что значит "нарушается типовая безопасность"?
и ещё один вопрос. где можно достать инфу под названием типа
"каким образом компилятор переводит текст на С++ в машинные комманды". я, конечено, понимаю, что разные компиляторы делают
это по-разному, но всё-таки хотелось бы разъяснить общие вопросы.
подобные преобразования вполне безопасны. я так понял?
[/QUOTE]
Нет, подобные преобразования не безопасны даже если ты "знаешь, что делаешь". Подобная практика является плохим стилем программирования, которого следует избегать с самого начала.
[QUOTE=smax13]
что значит "нарушается типовая безопасность"?
[/QUOTE]
Это свойство языков программирования высокого уровня.
Всегда должно быть известно кокого типа объект, причем это обеспечивается самим языком (его конструкциями), а не внешней информацией (комментарием в коде или на бумажке).
При приведении типов, которое ты описываешь, теряется информация о типе, т.е. без внешней информации становится не понятным, на что в действительности указывает твой указатель. В программировании на С++ эта проблема называется "проблема void*", что является нарушением типовой безопасности.
подобные преобразования вполне безопасны. я так понял?
что значит "нарушается типовая безопасность"?
[/QUOTE]
Это значит, если ты ВДРУГ запишешь в массив lpmas указатель на что-то другое вместо CLASS, получишь полную хрень. А компилятор даже не пикнет. Под безопасностью в данном случае подразумевается то, что компилятор может выявить случайно допущенные программистом ошибки.
[QUOTE=smax13]
и ещё один вопрос. где можно достать инфу под названием типа
"каким образом компилятор переводит текст на С++ в машинные комманды". я, конечено, понимаю, что разные компиляторы делают
это по-разному, но всё-таки хотелось бы разъяснить общие вопросы.[/QUOTE]
Не знаю, где ты сможешь достать подобную инфу, лучше спрашивай здесь, что конкретно тебя интересует.
1. Указатели в 32-битных Windows-системах действительно 32-битные и представляют собой просто смещение от 0-го адреса.
2. В 16-битных системах (Windows 3.11, DOS) указатели были 2 видов - дальние (с ключевым словом far) 32-битные (сегмент + смещение, возможность адресации в пределах [0..0x10FFEF]) и ближние 16-битные (с ключевым словом near) (адресация в пределах 64 Кб, т. е. в пределах текущего сегмента).
3. На С/С++ - передача параметра по ссылке и по указателю на уровне машинных кодов не отличаются. Передача ссылки - фактически тоже передача указателя.
4. Ну и естественно указатели на разные типы никак между собой не отличаются на уровне машинных кодов. НО ОСТОРОЖНЕЕ с преобразованиями указателей на объекты производных классов. Там компилятор может изменить само значение указателя; такое, например, может происходить при множественном наследовании.
Если очень хочеться, то пиши в C. C даст тебе полный контроль за всеми указателями. И, кроме того, насколько я помню спецификации, ANSI C++ скажет тебе "error: ..."
[/QUOTE]
Ты не прав. Это не случайность, а закономерность.
[QUOTE=foo]
при наличии виртуальных функций, компилятор запросто может поместить указатель на vtable до того места куда указывает указатель. То есть это может работать с одним компилятором, но при этом не работать с другим.
[/QUOTE]
То же не верно. Это будет работать с любым компилятором.
[QUOTE=foo]
Если очень хочеться, то пиши в C. C даст тебе полный контроль за всеми указателями.
[/QUOTE]
Да и С++ дает "полный контроль за всеми указателями".
[QUOTE=foo]
И, кроме того, насколько я помню спецификации, ANSI C++ скажет тебе "error: ..."[/QUOTE]
Спецификации или стандарт?
Конкретный пункт, плз.
То же не верно. Это будет работать с любым компилятором.
Да и С++ дает "полный контроль за всеми указателями".
[/QUOTE]
да? возможно в данной ситуации ты прав. Но если хочешь, я найду пример, когда такого рода преобразование приводит к SEGFAULT ("программа выполнила некорректную операцию..." в терминологии виндовс). Правда, там имеет место быть наследование.
Пример, который продемонстрирует, что нету полного контроля над указателями в C++.
[QUOTE=Green]Спецификации или стандарт?
Конкретный пункт, плз.[/QUOTE]
вот тут ты прав. память меня подвела... Уж и не помню, что там к чему я приводил, что без reinterpret_cast у нифига не вышло, но в данном случае действительно всё работает. И работает согласно стандарту.
Пример, который продемонстрирует, что нету полного контроля над указателями в C++.
[/QUOTE]
Чтож интересно было бы посмотреть.
Только сдается мне, что ты путаешь преобразования type1* -> void* -> type1* и type1* -> void* -> type2*, где type2 может быть в наследственной связи с type1.
Мы же говорим ТОЛЬКО про первый вариант (type1* -> void* -> type1*).
перегрузить операторы long* для класса, да и точка =)
Или просто для прикола?
н-и-ч-е-г-о
если в локальной области видимости определены
{
char szstr[] = "aaaaa";
char* szstr = "aaaaa";
}
различаются ли они по времени жизни?
есть ли аналогия между второй строкой и, например,
CLASS* pclass = new CLASS;