Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Базовые и порожденные классы  (Прочитано 37290 раз)
0 Пользователей и 7 Гостей смотрят эту тему.
ezus
Опытный

il
Offline Offline

« : 25-08-2010 10:39 » 

Опять запутался в языках и что-то не понимаю в С++.

Есть 2 класса Pattern и Shape, которые наследуют от общего класса Keta.
Код:
class Keta  
{
public:
Keta();
virtual ~Keta();
bool _isPattern;
virtual void locate()=0;
};
class Pattern : public virtual Keta
{
public:
Pattern();
virtual ~Pattern();
void fp();
void locate();
};
class Shape : public virtual Keta
{
public:
Shape();
virtual ~Shape();
void fs();
void locate();
};

Есть смешанный массив указателей на оба класса
Код:
CPtrArray arr;  arr.SetSize(0,1);
Pattern* ptr = new Pattern;
arr.Add(ptr);

Shape* shp = new Shape;
arr.Add(shp);
Читая этот массив, я естесственно не знаю тип текущего объекта, поэтому

Keta* keta = (Keta*)arr.GetAt(i);

1. Могу ли я, зная исходный тип объекта, получить указатель соответствующего типа?
Например:
Код:
if( keta->_isPattern )
Pattern* ptr = (Pattern*)keta:
или
Pattern* ptr = keta:

2. В чем моя ошибка в определении виртуальной функции    
virtual void locate()=0; ?

Программа падает при
keta.locate();

Спасибо.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 25-08-2010 11:00 » 

1) можно, но не нужно
2)а код функций void locate() покажи )
« Последнее редактирование: 25-08-2010 11:01 от Алексей1153++ » Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #2 : 25-08-2010 11:20 » 

можно и иногда нужно
можно доже если ты не знаешь тип элемента Улыбаюсь при использовании RTTI и dynamic_cast
http://alenacpp.blogspot.com/2005/08/c.html
Записан

Странно всё это....
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #3 : 25-08-2010 11:30 » 

1) можно, но как сказал пушистый не нужно, но если очень хочется, то так
Keta* object = (Keta*)arr.GetAt(i);
Pattern * pattern = 0;
Shape * shape = 0;

pattern = dynamic_cast<Pattern *>(object);
if (!pattern)
{
  shape = dynamic_cast<Shape *>(object);
  if (!shape)
    ;// ЖОПА
}

2) падает в рантайме или просто ошибка при компиляции или линковке, если в рантайме, то код ошибки и реализацию метода в потомке показывай
Записан

С уважением Lapulya
ezus
Опытный

il
Offline Offline

« Ответ #4 : 25-08-2010 11:37 » 

1) можно, но не нужно
Нужно.
В случае Pattern необходимо выполнить функцию fp();
а  случае Shape необходимо выполнить функцию fs();
Заранее хочу отметить, что имена этих функций разные, потому что они просто разные.
Цитата
2)а код функций void locate() покажи )
void Pattern::locate() { puts("Pattern::locate\n"); }
void Shape::locate() { puts("Shape::locate\n");  }
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #5 : 25-08-2010 11:41 » 

1) тебе виднее на сколько они разные, но в любом лучае ответ дан. Кстати, операция dynamic_cast не быстрая, так что думай!
2) еще раз говорю
Цитата
падает в рантайме или просто ошибка при компиляции или линковке, если в рантайме, то код ошибки
Записан

С уважением Lapulya
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #6 : 25-08-2010 11:58 » 

Нужно.
В случае Pattern необходимо выполнить функцию fp();
а  случае Shape необходимо выполнить функцию fs();
Заранее хочу отметить, что имена этих функций разные, потому что они просто разные.

А полиморифизм на что? Объяви в Keta, одну виртуальную ф-ю f() и переопредели её в Pattern с телом fp и с телом fs в Shape. В чём проблема?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
ezus
Опытный

il
Offline Offline

« Ответ #7 : 25-08-2010 12:02 » 

А что такое "object " в
Keta* object = (Keta*)arr.GetAt(i); ?

Это какой-то третий объект, отличный от того, что был помешен в arr?

Просто раньше я работал в Java, а там таких заморочек не возникало, поэтому я никак не могу проникнуться кишками С++.
Записан
ezus
Опытный

il
Offline Offline

« Ответ #8 : 25-08-2010 12:06 » 

Нужно.
В случае Pattern необходимо выполнить функцию fp();
а  случае Shape необходимо выполнить функцию fs();
Заранее хочу отметить, что имена этих функций разные, потому что они просто разные.

А полиморифизм на что? Объяви в Keta, одну виртуальную ф-ю f() и переопредели её в Pattern с телом fp и с телом fs в Shape. В чём проблема?
Я же отметил, что это ПРИНЦИПИАЛЬНО разные функции, и объединять их под общим именем не вижу никакого смысла, кроме чисто программистских заморочек, которых всегда старался избегать.
Записан
ezus
Опытный

il
Offline Offline

« Ответ #9 : 25-08-2010 12:07 » 

За
 Pattern* ptr = dynamic_cast<Pattern *>(keta);
СПАСИБО.

Но я получаю
warning C4541: 'dynamic_cast' used on polymorphic type 'class Keta' with /GR-; unpredictable behavior may result

Как можно избежать данного предупреждения?
Записан
ezus
Опытный

il
Offline Offline

« Ответ #10 : 25-08-2010 12:11 » 

На
Keta* keta = (Keta*)arr.GetAt(i);
keta->locale();

получаю
"Unhandled exception in tst.exe: 0x0000005: Access Violation"
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #11 : 25-08-2010 12:22 » 

Я же отметил, что это ПРИНЦИПИАЛЬНО разные функции, и объединять их под общим именем не вижу никакого смысла, кроме чисто программистских заморочек, которых всегда старался избегать.

Если имя ф-ции как заноза в глазу, назови её CallSpecialFunction() и тогда

Код:
void Pattern::CallSpecialFunction()
{
      fp();
}

...

void Shape::CallSpecialFunction()
{
      fs();
}


Ну, если ООП чисто программисткая заморочка, то зачем его использовать? Есть прекрасное функциональное программирование. А в данном случае, как раз притягивание типов за уши для этой цели, есть в высшей степени нелепость. Ибо переписанные функции классов-потомков просто обязаны быть ПРИНЦИПИАЛЬНО разными, иначе нафига они вобще нужны?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #12 : 25-08-2010 12:43 » 

Джон, ezus правильно говорит, нельзя так делать, если следовать твоему предложению, то:
1. Это уже не наследование по логике (наследуемые классы наследуют поведение предка, а тут сразу нарушение этого правила)
2. Так можно решить только частную задачу, ну например, у меня таких массивов 100 штук и в каждом из них должна быть разная обработка объектов в зависимости от типа, чтож мне миллион функций в эти классы впихать, чтоб при любой обработке вызвать одну, но виртуальную?

Но, у тебя проблема в проектировании, возможно надо дополнительно хранить отдельные массивы в каждом из которых хранятся строго определенные по типу объекты и т.д. ИМХО использования dynamic_cast надо по возможности избегать, а его наличие в исходнике - с высокой долей вероятности - это следствие неудачно выбранной архитектуры.

Цитата
Код:
Keta* keta = (Keta*)arr.GetAt(i);
keta->locale();

получаю
"Unhandled exception in tst.exe: 0x0000005: Access Violation"

Чему равно:
1. keta при вызове?
2. верно ли, что объект вынутый из массива действительно типа Keta (т.е. dynamic_cast<Keta*>(arr.GetAt(i)) вернет не 0)?
« Последнее редактирование: 25-08-2010 12:45 от lapulya » Записан

С уважением Lapulya
ezus
Опытный

il
Offline Offline

« Ответ #13 : 25-08-2010 12:48 » 

Я чувствую - начали переходить на личности?
Очень бы не хотелось.
Попробую ответить корректно.

Если имя ф-ции как заноза в глазу, назови её CallSpecialFunction() и тогда
Фунция "CallSpecialFunction()" будет такой же "занозой в глазу" как и любая другая.
Функция должна рождаться из задачи, а если это не так, то она именно "программисткая заморочка", и их надо минимизировать, оставляя только самые необходимые, без которых на данной платформе задача просто не решается.
Цитата
Ну, если ООП чисто программисткая заморочка, то зачем его использовать?
Мне кажется вы путаете ООП с С++. Это далеко не одно и тоже.

Цитата
Есть прекрасное функциональное программирование. А в данном случае, как раз притягивание типов за уши для этой цели, есть в высшей степени нелепость.
Причем здесь "прекрасное функциональное программирование"?
И в чем заключается "притягивание типов за уши для этой цели"?
Какой цели?
И в чем "высшая степень нелепости"?

Цитата
Ибо переписанные функции классов-потомков просто обязаны быть ПРИНЦИПИАЛЬНО разными, иначе нафига они вобще нужны?
Интересный взгляд на ООП.
Т.е. полиморфизм подразумевает, что в одном случае виртуальная фунция "расчет сметы" будет выполнять чистку базы данных, а в другом печать расписания паровозов?

Записан
ezus
Опытный

il
Offline Offline

« Ответ #14 : 25-08-2010 12:51 » 

Чему равно:
1. keta при вызове?
2. верно ли, что объект вынутый из массива действительно типа Keta (т.е. dynamic_cast<Keta*>(arr.GetAt(i)) вернет не 0)?
Код:
	Pattern* ptr = new Pattern;
arr.Add(ptr);
Keta* keta = (Keta*)arr.GetAt(0);
keta->locate();
Записан
ezus
Опытный

il
Offline Offline

« Ответ #15 : 25-08-2010 12:55 » 

Похоже я насщупал ошибку, хотя все равно не понимаю.
Вместо
arr.Add(ptr);
надо
arr.Add((Keta*)ptr);

И тогда похоже работает.
Жалко, что проверить смогу только завтра.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #16 : 25-08-2010 13:00 » 

ну наверное не так
Цитата
Код:
Pattern* ptr = new Pattern;
,а так
Код:
Pattern* ptr = new Pattern();

И чему всеже равно keta?

Цитата
Код:
Pattern* ptr = new Pattern;
arr.Add(ptr);
Keta* keta = (Keta*)arr.GetAt(0);
keta->locate();
Был ли arr пуст?
Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #17 : 25-08-2010 13:01 » 

Цитата
Похоже я насщупал ошибку, хотя все равно не понимаю.
Вместо
arr.Add(ptr);
надо
arr.Add((Keta*)ptr);

Не, тут по идее никакой разницы (т.е. это абсолютно одно и тоже).
Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #18 : 25-08-2010 13:06 » 

ezus,  это

Цитата
Но, у тебя проблема в проектировании, возможно надо дополнительно хранить отдельные массивы в каждом из которых хранятся строго определенные по типу объекты и т.д. ИМХО использования dynamic_cast надо по возможности избегать, а его наличие в исходнике - с высокой долей вероятности - это следствие неудачно выбранной архитектуры.

я не Джону, а тебе писал Улыбаюсь
Записан

С уважением Lapulya
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 25-08-2010 13:14 » 

Просто раньше я работал в Java, а там таких заморочек не возникало, поэтому я никак не могу проникнуться кишками С++.
Указатель в С++ ~= ссылке (ссылочному типу) в Java, с поправкой на то, что управления временем жизни и сборки мусора нет, а прямая адресация памяти открывает бескрайние просторы для всякого. Соответственно, как указатели ни приводи, объект фактически будет существовать один - тот, который создан, в данном случае, конструкцией new Type; (конструктором по умолчанию на куче). Всё остальное ссылается именно на эту область памяти. И надо не забыть его удалить, т.к., см. выше, сборки мусора нет.
Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 25-08-2010 13:40 » 

Цитата
Похоже я насщупал ошибку, хотя все равно не понимаю.
Вместо
arr.Add(ptr);
надо
arr.Add((Keta*)ptr);

Не, тут по идее никакой разницы (т.е. это абсолютно одно и тоже).

Разница есть, она в том, что в первом случае происходит преобразование Pattern* -> void*, а во втором - Pattern*->Keta*->void*. Преобразование Pattern*->void*->Keta* будет некорректным (рекомендую попробовать), потому что таблицу виртуальных функций класса Pattern поломает начисто - он ведь виртуально отнаследован.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #21 : 25-08-2010 14:18 » 

Джон, ezus правильно говорит, нельзя так делать, если следовать твоему предложению, то:
1. Это уже не наследование по логике (наследуемые классы наследуют поведение предка, а тут сразу нарушение этого правила)

Из чего следует это утверждение? А если это просто интерфейсная ф-я? О каком поведении предка и наследовании этого поведения можно вобще говорить, если это абстрактный (мне больше нравится слово "интерфейсный" или просто "интерфейс") класс? Или ты можешь описать поведение объекта Keta? Ага ООП как раз и предоставляет возможность разрешить проблему "персонализации" объекта при вызове специальной ф-ции. Есть указатель только на родительский класс. Всё. Больше ничего. Какая разница, что там воплощено. Это уже головная боль потомка.

2. Так можно решить только частную задачу, ну например, у меня таких массивов 100 штук и в каждом из них должна быть разная обработка объектов в зависимости от типа, чтож мне миллион функций в эти классы впихать, чтоб при любой обработке вызвать одну, но виртуальную?

Ничего не понял. Если у тебя таких массивов миллион, то ф-я всё-равно будет одна.

Я чувствую - начали переходить на личности?

Ни в коем случае. Ничего личного. Я просто в своё время сам проходил через это - преобразование родительского типа к конкретному. Любое такое преобразование - проявление анти ООП настроений. Указывет исключительно на слабо продуманную архитектуру. Прочитай, первые три ответа на свой первый вопрос, заметь, других участников. Поэтому на личности перехода нет и не будет.

Цитата
Фунция "CallSpecialFunction()" будет такой же "занозой в глазу" как и любая другая.
Функция должна рождаться из задачи, а если это не так, то она именно "программисткая заморочка", и их надо минимизировать, оставляя только самые необходимые, без которых на данной платформе задача просто не решается.

Согласен и 100% поддерживаю, но только когда речь идёт о реализации какой-то конкретной, чётко сформулированной задачи. Но когда одна ф-я выполняет работу целой библиотеки, это тоже не есть гут. Согласись? В этом случае такого монстра необходимо разбить на более мелкие задачи, что автоматически повлечёт за собой производство кучи маленьких вспомогательных ф-ций. В твоём же случае, речь идёт о ф-ции, которая управляет другими ф-ми, она их вызывает. Что же в этом плохого? Немного другая степень абстракции.

Цитата
Мне кажется вы путаете ООП с С++. Это далеко не одно и тоже.
В чём? Я как раз очень хорошо знаю, что С++ это далеко не идеальный язык для ООП. Поэтому в последнее время всё чаще и чаще повторяю одну очень хорошую мысль Трея Нэша, даже вынес её в подпись:
"Just because the language allows you to do something does not mean that it’s the correct thing to do."

Как раз такой случай, то что С++ позволяет приводить типы, ещё не значит, что надо так всегда делать.

Цитата
Причем здесь "прекрасное функциональное программирование"?
Ну как при чём, именно  оно позволяет создать минимум функций для реализации конкретной задачи. Без всяких заморочек. Или не так?

Цитата
И в чем заключается "притягивание типов за уши для этой цели"?

Вот в этом:

if( keta->_isPattern ) Pattern* ptr = (Pattern*)keta

Твой пример только для наглядности (никаких личностей). Также это относится и к безопасным кастингам а ля dynamic_cast.

Цитата
Какой цели?
Вызвать специальную, существующую только в этом классе (кстати потомке) ф-ю.

Цитата
И в чем "высшая степень нелепости"?

Ну сравни сам это:

Код:
Keta* object = (Keta*)arr.GetAt(i);
Pattern * pattern = 0;
Shape * shape = 0;

pattern = dynamic_cast<Pattern *>(object);
if (!pattern)
{
  shape = dynamic_cast<Shape *>(object);
  if (shape)
  {
      pattern->fs();
  }
   else
   {
        // ЖОПА
   }
}
else
{
     pattern->fp();
}

и это:

Код:
Keta* object = (Keta*)arr.GetAt(i);
object->f();


Цитата
Интересный взгляд на ООП. Т.е. полиморфизм подразумевает, что в одном случае виртуальная фунция "расчет сметы" будет выполнять чистку базы данных, а в другом печать расписания паровозов?

КОНЕЧНО! Ибо глупость человеческая, в отличие от вселенной, безгранична. Если, ТАК спроектировать, то будет не только расписание паровозов. Ага На самом деле всё гораздо проще. Классический пример с геометрическими фигурами. Чертить окружность есть совсем не то, что строить треугольник. Но оба они представляют собой некий процесс. Поэтому родительский класс Фигура получает ф-ю Нарисовать(). А уже Треугольники, Квадраты и прочие дети, сами выполняют то, что им нужно.
Если два класса имеют общего предка, то значит их что-то объединяет. Иначе предок не нужен вобще. Поэтому и ф-ции предка, имеют как правило обобщённый смысл. Рисовать, Удалить, Переместить. А "расписание паровозов" и "расчет сметы" всё-таки узкоспециаллизированные задачи. Поэтому они не могут напрямую выполняться какими-то прямыми потомками одного родителя. Как я уже сказал, всё зависит от архитектуры проекта.
Если это имеет смысл, то какой-нить класс-потомок в десятом колене, действительно будет вычислять смету, а его десятиюродный братец в это же вермя расписывать паровозы, и оба, как результат некоего общего начального действия.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #22 : 25-08-2010 15:33 » 

Цитата
Из чего следует это утверждение? А если это просто интерфейсная ф-я? О каком поведении предка и наследовании этого поведения можно вобще говорить, если это абстрактный (мне больше нравится слово "интерфейсный" или просто "интерфейс") класс? Или ты можешь описать поведение объекта Keta?  ООП как раз и предоставляет возможность разрешить проблему "персонализации" объекта при вызове специальной ф-ции. Есть указатель только на родительский класс. Всё. Больше ничего. Какая разница, что там воплощено. Это уже головная боль потомка.

см свой же пример с геометрическими фигурами, там ты сам отвечаешь на свой вопросы (и с базовым абстрактным, т.е. есть интерфейс поведения - фигуры рисуются, а так же наследников, которые в функции draw именно рисуются, а не рассчитывают зарплату)

Цитата
Ничего не понял. Если у тебя таких массивов миллион, то ф-я всё-равно будет одна.

я наверное криво написал, я имел ввиду, что у каждого массива (а их 100) своя уникальная! обработка. Ну например у массива один мне надо у объектов Pattern навести ракету на цель (т.е. он целится), а у объектов Shape лечить раненых (т.е. оказать медицинскую помощь). В то же время при обработке массива 2 мне надо Pattern произвести выстрел, а Shape окопаться и т.д.. При этом Тип Kate это объект описывающий Unit (у которого есть общие для всех юнитов свойства, показатели здоровья и скорости и т.д.)

Цитата
Цитата
Я чувствую - начали переходить на личности?

Ни в коем случае. Ничего личного.

Полностью поддерживаю.

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

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

Цитата
Классический пример с геометрическими фигурами. Чертить окружность есть совсем не то, что строить треугольник. Но оба они представляют собой некий процесс. Поэтому родительский класс Фигура получает ф-ю Нарисовать(). А уже Треугольники, Квадраты и прочие дети, сами выполняют то, что им нужно.
Если два класса имеют общего предка, то значит их что-то объединяет. Иначе предок не нужен вобще. Поэтому и ф-ции предка, имеют как правило обобщённый смысл. Рисовать, Удалить, Переместить. А "расписание паровозов" и "расчет сметы" всё-таки узкоспециаллизированные задачи. Поэтому они не могут напрямую выполняться какими-то прямыми потомками одного родителя. Как я уже сказал, всё зависит от архитектуры проекта.

Вот в этом и есть наследование поведения! функция рисует или удаляет занимается именно рисованием (удалением соответственно), а вот как она это делает ее личное дело.

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

А вот тут нет. Такого быть не должно, ибо действия принципиально различны.
Записан

С уважением Lapulya
ezus
Опытный

il
Offline Offline

« Ответ #23 : 25-08-2010 18:21 » 

Спасибо, Вы за меня написали практически все мои возражения.
Записан
ezus
Опытный

il
Offline Offline

« Ответ #24 : 25-08-2010 18:44 » new

To Джон.
А какая с Вашей точки зрения должна быть структура объектов в следующей задаче - в соответствием с ООП.
Обработка данных о людях. Естественно у женщин и мужчин есть как много общих данных\функций\алгоритмов, так и исключительно специфических. Мне хотелось бы иметь для них 2 разных класса. Мне кажется очевидным использовать для общих данных и функций базовый класс. Вопрос - как хранить данные о людях, если основная обработка связанна с общими функциями, а специфика проявляется изредка в частных случаях. Например - поликлиника. 80% болячек общие, но иногда необходимо выполнить исключительно женские или мужские проверки. Вести параллельно 2 массива или 1.  А если 1, то как перейти к специфике?
Записан
ezus
Опытный

il
Offline Offline

« Ответ #25 : 25-08-2010 18:50 » 

ну наверное не так
Цитата
Код:
Pattern* ptr = new Pattern;
,а так
Код:
Pattern* ptr = new Pattern();
А в чем разница? Может тут собака порылась.
Записан
ezus
Опытный

il
Offline Offline

« Ответ #26 : 25-08-2010 18:51 » 

.
« Последнее редактирование: 25-08-2010 19:09 от ezus » Записан
ezus
Опытный

il
Offline Offline

« Ответ #27 : 25-08-2010 18:59 » 

Просто раньше я работал в Java, а там таких заморочек не возникало, поэтому я никак не могу проникнуться кишками С++.
Указатель в С++ ~= ссылке (ссылочному типу) в Java, с поправкой на то, что управления временем жизни и сборки мусора нет, а прямая адресация памяти открывает бескрайние просторы для всякого. Соответственно, как указатели ни приводи, объект фактически будет существовать один - тот, который создан, в данном случае, конструкцией new Type; (конструктором по умолчанию на куче). Всё остальное ссылается именно на эту область памяти. И надо не забыть его удалить, т.к., см. выше, сборки мусора нет.
Скорее всего ты прав.
Но в Java это действительно ОДИН объект, и ты просто смотришь на него через разные маски, будь то базовый класс или интерфейсы. Поэтому подобные кастинги естественны и безболезненны. А в С++ похоже не так.
А вот КАК, хотелось бы понять.
Записан
ezus
Опытный

il
Offline Offline

« Ответ #28 : 25-08-2010 19:08 » 

И все-таки может быть кто-нибудь знает - как избежать предупреждения

warning C4541: 'dynamic_cast' used on polymorphic type 'class Keta' with /GR-; unpredictable behavior may result

?
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #29 : 25-08-2010 19:26 » 

lapulya, я "коротко" отвечу, нет ни времени ни желания вдаваться в полемику. Никакого противоречия нет. Я же сказал, примитивненький примерчик. Для начинающих. Поэтому и ф-я называется в всех случаях - Рисуй(). А представь себе, что куча функциональных объектов должна запуститься в определённой последовательности. Например, сбор информации, обработка, вывод результата. Тогда каждый из этих объектов получит ф-ю, например, StartProcess(). И что? Где наследование свойств родителя, и главное - каких? Ага

Конечно же наследование свойств родителя имеет место быть. Например, когда родитель содержит общие для всех деток поля
данных. Тогда и поведение родителя наследуется детьми, например ф-я инициаллизации. Но в таком случае обычно дети сначала вызывают родительскую ф-ю, а потом уже инициаллизируют свои индивидуальные поля данных. В этом случае можно говорить о наследовании свойства родителя - инициаллизации. Но если родитель содержит "чиста" Ага виртуальные (pure virtual) методы, то он автоматически превращается в интерфейс и в этом случае ни о каком вызове "базовых" ф-ций не может быть и речи. В этом случае "наследование свойств родителя" является фиктивным и определяется только семантикой методов: назови метод Сверлить() - и детки уже не смогут Поливать(), а  назови Процесс() - и дашь детям свободу стрелять, окапываться и пр. Ага

Ну примерно в таком аспекте. Хотя, я думаю, это и так ясно.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines