работа с классами в Си++
Я не могу понять как соеденить все объекты этих классов(точка, круг, квадрат и правильный треугольник) в список(динамический).
Подскажите кто знает.
Я не могу понять как соеденить все объекты этих классов(точка, круг, квадрат и правильный треугольник) в список(динамический).
Тебе надо порождать ети обекты от базового класа с виртуальными функциями (смотри документацию по ООП). Делаеш масив указателей на базовый клас. Потом создаеш в динамической памяти екземпляри обектов тех класов что тебе нужны, а указатели на них запихиваеш в масив.
Тебе надо порождать ети обекты от базового класа с виртуальными функциями (смотри документацию по ООП). Делаеш масив указателей на базовый клас. Потом создаеш в динамической памяти екземпляри обектов тех класов что тебе нужны, а указатели на них запихиваеш в масив.
Я создал базовый класс и создал дочерние классы покаждой фигуре. У меня в базовом классе есть виртуальная функция paint(она рисует фигуру), которая переопределяется в каждом дочернем классе. Так если я сделаю список из объектов базового класса и буду вызывать функцию paint как компилятор поймёт к какому из дочерних классов относится эта функция(какую именно фигуру надо нарисовать). Или один базовый класс будет рисовать все фигуры?
Я создал базовый класс и создал дочерние классы покаждой фигуре. У меня в базовом классе есть виртуальная функция paint(она рисует фигуру), которая переопределяется в каждом дочернем классе. Так если я сделаю список из объектов базового класса и буду вызывать функцию paint как компилятор поймёт к какому из дочерних классов относится эта функция(какую именно фигуру надо нарисовать). Или один базовый класс будет рисовать все фигуры?
Я думаю, что ты будешь приводить указатели на базовый класс к указателям на производный и соответственно работать с методами производных классов.
Я думаю, что ты будешь приводить указатели на базовый класс к указателям на производный и соответственно работать с методами производных классов.
Тогда в чем смысл виртуальных методов?
как компилятор поймёт к какому из дочерних классов относится эта функция(какую именно фигуру надо нарисовать)
Думаю, не стоит тебе пока заморачиваться с тем, как это реализуется. Просто прийми на веру, что если указатель на базовый класс указывает на экземпляр производного класса, то вызов виртуального метода приведет к выполнению реализации его в производном классе.
В твоём же размышлении ошибка в том, что ты создаешь массив базовых объектов, а надо создавать массив указателей на базовый класс и присваивать им значения указывающие на созданные объекты производных классов.
Тогда в чем смысл виртуальных методов?
Если производных классов несколько и имя метода, одинаково, и список формальных параметров совпадает, то как компилятор,без явного приведения к типу, может узнать, метод какого класса вызывать?
А виртуальные методы нужны, чтобы переопределить их в производных классах. Например базовый класс фигура не может иметь конкретного метода прорисовки, так как фигура абстрактна.
Если производных классов несколько и имя метода, одинаково, и список формальных параметров совпадает, то как компилятор,без явного приведения к типу, может узнать, метод какого класса вызывать?
А виртуальные методы нужны, чтобы переопределить их в производных классах. Например базовый класс фигура не может иметь конкретного метода прорисовки, так как фигура абстрактна.
Молодой человек. Внимательней читайте посты. Вам же Green написал чистым русским языком: Массив указателей, а не массив объектов.
Молодой человек. Внимательней читайте посты. Вам же Green написал чистым русским языком: Массив указателей, а не массив объектов.
Это Вы внимательнее читайте.
Я с самого начала про указатели писал, а что вам надо понять вообще не могу.
Ко мне относилась только первая фраза грина и то не могу понять, к чему она была!
Если производных классов несколько и имя метода, одинаково, и список формальных параметров совпадает, то как компилятор,без явного приведения к типу, может узнать, метод какого класса вызывать?
Без явного приведения чего?
Указателя на базовый класс к указателю на производный?
Совершенно не нужно приводить, если работа идет через виртуальные методы. Для того они и есть.
Компилятор узнает по таблице виртуальных методов.
А виртуальные методы нужны, чтобы переопределить их в производных классах. Например базовый класс фигура не может иметь конкретного метода прорисовки, так как фигура абстрактна.
Это применение, а не цель.
Цель - отвязать интерфейс от реализации.
Это Вы внимательнее читайте.
Я с самого начала про указатели писал, а что вам надо понять вообще не могу.
Ко мне относилась только первая фраза грина и то не могу понять, к чему она была!
Судя по вашему посту:
я был прав. И стоит подумать, прежде чем обижаться. Или уж нахудой конец литературу почитать. Там все доступно написано.
Судя по вашему посту:
я был прав. И стоит подумать, прежде чем обижаться. Или уж нахудой конец литературу почитать. Там все доступно написано.
Я не обижаюсь.
В чем прав-то?!
Так я и не понял Ваших ко мне претензий...
И при чем здесь массив объектов?
Ладно, будем считать, что мы друг друга не допоняли.
И все же хотелось бы у грина выяснить в частном порядке, как он это все видит...
Я не обижаюсь.
В чем прав-то?!
Так я и не понял Ваших ко мне претензий...
И при чем здесь массив объектов?
Ладно, будем считать, что мы друг друга не допоняли.
И все же хотелось бы у грина выяснить в частном порядке, как он это все видит...
Вот выдержка из учебника по ООП.
3.5.1 Виртуальные функции
В ООП полиморфизм достигается не только описанным выше механизмом наследования и перегрузки методов родителя, но и виртуализацией, позволяющей родительским функциям обращаться к функциям потомков. Полиморфизм реализуется через архитектуру класса, но полиморфными могут быть только функции-члены.
В C++ полиморфная функция привязывается к одной из возможных одноименных функций только в момент исполнения, когда ей передается конкретный объект класса. Другими словами, вызов функции в исходном тексте программы лишь обозначается, без точного указания на то, какая именно функция вызывается. Такой процесс известен как позднее связывание.
Позднее связывание не подразумевает явного приведения типов. На то оно и позднее. Это вообще стандартный механизм ООП для реализации абстракций и классов - контейнеров. Понимание этого механизма приводит нас к выводу, что достаточно ссылки на базовый класс, для того, чтобы организовать список для классов потомков. А явное приведение в этом случае не нужно, а за частую и невозможно.
как он это все видит...
Все ту очень просто, вам толкуют, а вы на людей бросаетесь :)
1) Создаете базовай класс, например "фигура"
2) Создаете в нем виртуальную функцию "рисовать"
3) Создаете производные классы "квадрат", "круг" и т.п.
4) В каждом производном классе определяете функцию "рисовать"
5) Создаете сколько надо, каких надо объектов - квадратов, кругов и т.п.
6) Складываете указатели на эти объекты в массив, в список, в вектор - куда больше понравится.
7) Когда надо перерисовать, о перебираете эти указатели, приводите из к указателю на базовай класс "фигура" (в листе, например, они как void* лежат), и вызываете по этому указателю функцию "рисовать"
8) Наслаждаетесь как рисуются разные объекты.
И все же хотелось бы у грина выяснить в частном порядке, как он это все видит...
Видит решение задачи топика?
Вот так:
class Figure
{
public:
virtual void draw() = 0;
};
class Circle :public Figure
{
public:
void draw()
{
// implementation
}
};
class Box :public Figure
{
public:
void draw()
{
// implementation
}
};
int main()
{
std::list<Figure*> figures;
// Создание и добавление фигур
figures.push_back(new Circle);
figures.push_back(new Box);
// и т.д.
// Прорисовка
for(std::list<Figure*>::iterator it = figures.begin();
it != figures.end(); ++it)
{
(*it)->draw();
}
}
7) Когда надо перерисовать, о перебираете эти указатели, приводите из к указателю на базовай класс "фигура" (в листе, например, они как void* лежат), и вызываете по этому указателю функцию "рисовать"
Только этот пункт неверен.
Зачем хранить void*, а потом преобразовывть его к указателю на базовый класс?
Я уже не раз говорил, что в С++ можно и нужно обходится вообще без void*.
В остальном всё верно и именно так показывается в моём примере.
Зачем хранить void*, а потом преобразовывть его к указателю на базовый класс?
Я просто имел ввиду VCL'ный TList. Конечно лучше сразу хранить указатели на базовый класс.
Я просто имел ввиду VCL'ный TList. Конечно лучше сразу хранить указатели на базовый класс.
В TList тоже можно спокойно обойтись без void*
В TList тоже можно спокойно обойтись без void*
Может и можно, может и спокойно, я не знаю как.
Поделитесь секретом, если не жалко :)
Может и можно, может и спокойно, я не знаю как.
Поделитесь секретом, если не жалко :)
Не жалко:
Add, Count, Items example
{
PAList AStruct;
TList *MyList = new TList;
// fill the TList
AStruct = new TAList;
AStruct->I = 100;
AStruct->C = 'Z';
MyList->Add(AStruct);
AStruct = new TAList;
AStruct->I = 100;
AStruct->C = 'X';
MyList->Add(AStruct);
// Go through the list, writing the elements to the
// canvas of a paintbox component.
int Y = 10; // position on canvas
for (int i = 0; i < MyList->Count; i++)
{
AStruct = (PAList) MyList->Items;
PaintBox1->Canvas->TextOut(10, Y, IntToStr(AStruct->I));
Y += 30; // Increment Y Value again
PaintBox1->Canvas->TextOut(10, Y, AStruct->C);
Y += 30; //Increment Y Value
}
// Clean up – must free memory for the items as well as the list
for (int i = 0; i < MyList->Count; i++)
{
AStruct = (PAList) MyList->Items;
delete AStruct;
}
delete MyList;
}
Не жалко:
Не понял, честно говоря. Вот я вижу преобразование элемента из void* к указателю некоторого другого типа:
Я разве не об этом говорил.
Не понял, честно говоря. Вот я вижу преобразование элемента из void* к указателю некоторого другого типа:
Я разве не об этом говорил.
Значит я не понял. Я думал, что ты имеешь ввиду примерно следующее:
Зы: А то, что они в TList определены как void*. Ну куда же от этого денешься.
Зы: А то, что они в TList определены как void*. Ну куда же от этого денешься.
Использовать STL :D
За такой reinterpret_cast обычно бьют :D
Да, приводить к указателю на производный класс необязательно.
Я вообще-то не совсем это имел ввиду. Такое преобразование можно делать если человек твердо уверен, что void* указывает на объект того типа к которому производится приведение, но так как void* может указывать на что угодно, то и результатом может быть что угодно.
Имеется 4 вида фигуры: точка, круг, квадрат и правильный треугольник. Требуется создать программу, которая содержала бы список(динамический) из выше приведенных фигур и рисовала вращала, передвигала, увеличевала/уменьшала бы их на экране.
Я не могу понять как соеденить все объекты этих классов(точка, круг, квадрат и правильный треугольник) в список(динамический).
Подскажите кто знает.
Придеться поговорить с твоим бородатым преподом из угату!!! и тебе пипец придет!!)))
Придеться поговорить с твоим бородатым преподом из угату!!! и тебе пипец придет!!)))
Не знаю как у Вас, но у нас за такое постукивание и инвалидом могут сделать. Главное потом и не докажеш что не сам з третьего етажа упал :D