Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.71
Наталья1204
0 / 0 / 0
Регистрация: 30.08.2011
Сообщений: 4
#1

Виртуальные функции - C++

31.08.2011, 13:43. Просмотров 1751. Ответов 21
Метки нет (Все метки)

Составить программу в С Buildere. Объявить базовый класс с именем person {имя, возраст, группа}. Определить функцию show (), которая отображает информацию о человеке, как виртуальную функцию. Объявить производный класс student = {имя, возраст, группы, департамента}. Переопределить функцию show (), которая показывает студентов в порядке убывания по годам. ХЕЕЕЛП!!!!
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.08.2011, 13:43
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Виртуальные функции (C++):

виртуальные и чисто виртуальные функции - C++
Чем они отличаются?? если можно, с примерами. И как из виртуальной функции сделать чисто виртуальную? #include <iostream> using...

виртуальные функции - C++
сделать какой либо из методов класса виртуальным #include<iostream.h> #include<stdio.h> class chislo { int a; public: ...

Виртуальные функции - C++
Пожалуйста, подскажите как быть: class Circles; class Rectangs; class Snake { public: Circles *drr; void start1(); ...

Виртуальные функции - C++
Подскажите пожалуйста, как передать переменную из одной виртуальной функции в другую. Вот код программы работает правильно, но в остальных...

виртуальные функции - C++
Помогите пожалуйста, создать абстрактный класс Shape с двумя чисто виртуальными методами Area() и Print(). Определить производные классы ...

Виртуальные функции - C++
Пытаюсь понять что это такое но не понимаю. Может есть какие то болие понятные примеры , а то то что я смотрел не дало результата. ...

21
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
31.08.2011, 13:50 #2
Нехило так. Интересно. От человека значит наследуется класс студент, а затем оказывается что студентов (в классе студент) должно быть более одного, дабы переопределить функцию show по заданию. Бред.
1
Bers
Заблокирован
31.08.2011, 14:09 #3
1. Создаём класс Персоны, закладываем в него вирт. диструктор, вирт функцию Показа.
2. Наследуем студентов от персон.
3. Добавляем новое поле "департамента".
4. Добавляем статический ассоциативный массив мультимап<возвраст_студента, Указатель_на_этого_студента>

5. В конструкторе студентов реализуем автоматическую регистрацию нового студента в статическом мультемапе.

6. Создадим у студентов функцию: ПоказатьСебя(); //которая выдаст на экран информацию об этом студенте.

7. Переопределяем виртуальную функцию показа, которая пробежится по мультимапу, и дергая из него указатели студентов, каждому студенту сделает: pStudents -> ShowMe();

8. После того, как все студенты отчитались о себе, добавим в конце послание преподавателю: ТАК ДЕЛАТЬ НЕЛЬЗЯ! СТУДЕНТЫ НЕ ДОЛЖНЫ ЗНАТЬ О СУЩЕСТВОВАНИИ ДРУГИХ СТУДЕНТОВ. ОШИБКА АРХИТЕКТУРЫ.
2
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.08.2011, 16:46 #4
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
#include <string>
#include <map>
using std::iterator;
using std::multimap;
using std::make_pair;
using std::string;
using std::cout;
 
class Person
{
public:
 
    Person(){};
    virtual ~Person(){};
    virtual void Show(void)=0;
    string age;
    string name;
};
 
static multimap<string,Person*> MAP;
 
 
class Stud : public Person
{
 
public:
    Stud(string ag, string nam)
    {
        
        age =ag;
        name = nam;     
        MAP.insert(make_pair<string,Person*>(age,this));
 
    
        
    };
    ~Stud(){};
    multimap<string,Person*>::iterator IT;
 
    void Show(){ShowMe();};
    void ShowMe()
    {
        IT = MAP.begin();
        while(IT!=MAP.end())
        {       
 
            cout<<IT->first<<"  "<<IT->second->name<<"\n";
            IT++;
        }
        IT = MAP.begin();       
    };
    
};
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    
Stud a("14","Ivan");
Stud b("13","Ivan");
Stud c("12","Ivan");
Stud d("13","Ivan");
a.Show();
 
    return 0;
    
}
Берсовский вариант
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.08.2011, 16:48 #5
выход
0
Изображения
 
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
31.08.2011, 16:58 #6
Делать нечего...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <map>
#include <functional>
#include <iterator>
#include <string>
#include <iostream>
 
class Person
{
public:
   Person(std::string name, short age, std::string group):name_(name), age_(age), group_(group)
   {
   }
   virtual ~Person() { }
   std::string get_name() const {return name_;}
   short get_age() const {return age_;}
   std::string get_group() const {return group_;}
   virtual void show(std::ostream& os) const
   {
       os << "Name: " << name_ << std::endl
           << "Age: " << age_ << std::endl
           << "Group: " << group_ << std::endl;
   }
protected:
   std::string name_;
   short age_;
   std::string group_;
};
 
class Student:public Person
{
public:
   Student(const std::string& name, short age, const std::string& group, const std::string& dep):
      Person(name, age, group), departement_(dep)
   {
       students.insert(std::make_pair(age, this));
   }
   std::string get_departement() const {return departement_;}
   virtual void show(std::ostream& os) const
   {
       for (std::multimap<short, const Student*, std::greater<short> >::const_iterator iter = students.begin(); iter != students.end(); ++iter)
       {
            iter->second->show_me(os);
       }
   }
private:
   static std::multimap<short, const Student*, std::greater<short> > students;
   std::string departement_;
   void show_me(std::ostream& os) const
   {
       Person::show(os);
       os << "Departement: " << departement_ << std::endl;
   }
};
 
std::multimap<short, const Student*, std::greater<short> > Student::students;
 
int main()
{
    Student stud("Vasya", 18, "1A", "BD");
    Student stud2("Vasya2", 19, "1B", "BD");
    Student stud3("Vasya3", 18, "1C", "FD");
    Student stud4("Vasya4", 17, "1D", "FD");
    stud4.show(std::cout);
}
Но препода за такое задание надо уничтожить.
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.08.2011, 17:07 #7
черт департамент забыл

Добавлено через 1 минуту
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 
#include <iostream>
#include <string>
#include <map>
using std::iterator;
using std::multimap;
using std::make_pair;
using std::string;
using std::cout;
 
class Person
{
public:
 
        Person(){};
        virtual ~Person(){};
        virtual void Show(void)=0;
        string age;
        string name;
        string department;
};
 
static multimap<string,Person*> MAP;
 
 
class Stud : public Person
{
 
public:
        Stud(string ag, string nam, string dept)
        {
                
                age =ag;
                name = nam;  
                department = dept;
                MAP.insert(make_pair<string,Person*>(age,this));
 
        
                
        };
        ~Stud(){};
        multimap<string,Person*>::iterator IT;
 
        void Show(){ShowMe();};
        void ShowMe()
        {
                IT = MAP.begin();
                while(IT!=MAP.end())
                {               
 
                        cout<<IT->first<<"  "<<IT->second->name<<"  "<<IT->second->department<<"\n";
                        IT++;
                }
                IT = MAP.begin();               
        };
        
};
 
 
int _tmain(int argc, _TCHAR* argv[])
{
        
Stud a("14","Ivan","sales");
Stud b("13","Ivan","tools");
Stud c("12","Ivan", "wh");
Stud d("13","Ivan","manger");
a.Show();
 
        return 0;
        
}
0
Bers
Заблокирован
31.08.2011, 17:09 #8
Цитата Сообщение от AzaKendler Посмотреть сообщение
Берсовский вариант
Не-не! Надо через for_each студентиков перебирать. Так круче))
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.08.2011, 17:11 #9
Bers, ну извини. пока только так.)
0
Bers
Заблокирован
31.08.2011, 17:59 #10
Цитата Сообщение от AzaKendler Посмотреть сообщение
Bers, ну извини. пока только так.)
Ну это ладно. Но обратите внимание:

Во-первых имя - МАП. Это никуда не годится. Оно не отражает сути. Что именно хранит внутри себя этот мап?

Во-вторых, как именно создан статический мультимап у вас?
Идеологически, он является внутренней частью реализации класса студентов. Но у вас он вообще вынесен за пределы класса, и доступ к нему можно получить из любой точки программы. Это - архитектурный промах. Он должен быть в приватной зоне класса-хозяина.

В-третьих, ключевые слова const. У вас их вообще нигде нету. А должны быть! Мы ведь боремся за гигиеническую чистоту нашего кода, правда ведь?

/зы присмотритесь к варианту господина ForEveRa.
Просто сравните. Вроде бы все тоже самое, но у него сразу чувствуется, что код писался
солидным, опытным программистом.

/ззы не сочтите за умника, я далеко не великий программист. И сам ещё только-только учусь.

Добавлено через 5 минут
Единственное, что мне не понятно в коде господина ForEveR, так это гм...

C++
1
2
3
4
5
6
virtual void show(std::ostream& os) const
   {
       os << "Name: " << name_ << std::endl
           << "Age: " << age_ << std::endl
           << "Group: " << group_ << std::endl;
   }
Если известно, что информация будит выводиться при помощи стандартного потока, то зачем было передавать объект потока в качестве аргумента?
Не проще ли, использовать обычный cout тогда?
1
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
31.08.2011, 19:25 #11
Bers, проще, но не дальновидно. А что, если в файл придется выводить?
0
AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
31.08.2011, 20:30 #12
Bers, ну все верно. много чего можно довести. Абсолютно со всем согласен. так это был просто выстрел от бедра от АзаКендлер)) когда все матерые кодеры послали тетю и только один Берс сформировал ТЗ и включил зеленый свет. А так..дешево и сердито. Разве нет? Ну похвали уже..Я ж учу еще.
И вообще, конечно однозначно надо все делать по науке, но не в ущерб общей мысли. тут где то была темка там просили составить Хэллоу уорд! От там парни поизгалялись. И так и эдак выкручивали с этой надписью. Думаю чем проще и ближе к заданию тем лучше. Надо вывести - на.

Добавлено через 17 минут
Цитата Сообщение от ForEveR Посмотреть сообщение
std::string name, short age, std::string group
ну и если честно и объективно, если std::string например часто проходит по тексту, разве не правильней его вынести в using?
просто я как новичок могу подумать что так и надо делать всегда полные объявления
0
Jupiter
Каратель
Эксперт С++
6558 / 3979 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
31.08.2011, 20:42 #13
Цитата Сообщение от AzaKendler Посмотреть сообщение
ну и если честно и объективно, если std::string например часто проходит по тексту, разве не правильней его вынести в using?
просто я как новичок могу подумать что так и надо делать всегда полные объявления
слишком много using std::* придется писать, лучше уж локально прописать
C++
1
2
3
4
5
6
void f()
{
    using namespace std;
    string a;
    ...
}
0
Bers
Заблокирован
31.08.2011, 21:28 #14
Цитата Сообщение от ForEveR Посмотреть сообщение
Bers, проще, но не дальновидно. А что, если в файл придется выводить
Понял)

Но тогда получается, что:

1. Придётся, предварительно ручками подготавливать поток вывода, и передавать его явно в качестве параметра, что бы класс сделал свою работу. (Излишняя нагрузка на вызывающую сторону)

2. Вызывающей стороне придётся самостоятельно контролировать, корректность работы потока, передаваемого объекту класса, в качестве параметра. В частности, проверять смог ли поток успешно открыть файл, или нет, и не забывать сделать потоку close()

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

Лично я считаю, что если вдруг приспичило выводить результат ещё и в файл - лучше добавить специализированный метод, принимающий в качестве параметра имя файла. Метод сам откроет файл в соответствии с новой задачей: в режиме перезаписи, или ещё как то...
И сам проверит успешность всей операции.

Ведь класс для того и создаётся: с целью облегчить жизнь вызывающей стороне, избавить её от львиной части рутины, по подготовкам и проверкам.
Он должен быть максимально устойчивым к ошибкам, а следовательно - принимать извне как можно меньше параметров.

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

Можно вылечить за счет добавления в зоне инициализации:
Подготовка класса к работе:

Студент.SetShowMode(Режим); //здесь можно задать так, что бы студент результат писал в файл
//метод сам подготовит поток вывода в соответствии с режимом, и проверит успешность всех операций

...

Cтудент.Show(); //Сам же вывод по прежнему без изменений. Нигде в программе править не придётся.

Добавлено через 10 минут
Цитата Сообщение от AzaKendler Посмотреть сообщение
Ну похвали уже..Я ж учу еще.
0
CyBOSSeR
Эксперт С++
2303 / 1673 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
01.09.2011, 01:41 #15
Цитата Сообщение от AzaKendler Посмотреть сообщение
ну и если честно и объективно, если std::string например часто проходит по тексту, разве не правильней его вынести в using?
Нет, лучше сразу забудьте о существовании этой директивы. Даже если пространство имен очень длинновато, то лучше вместа using сделать на него alias:
C++
1
2
3
4
5
namespace fs = boost::filesystem;
 
//...
bool exists = fs::exists(fileName);
//...
1
01.09.2011, 01:41
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.09.2011, 01:41
Привет! Вот еще темы с ответами:

виртуальные функции - C++
C++ подскажите пожалуста на словах код писать ненадо. как преопределить функцию virtual Print(). Создать абстрактный базовый класс...

Виртуальные функции - C++
Здравствуйте, помогите пожалуйста с вопросом: Заданный порожденный класс, содержащий две функции по таким именно именами, как и в...

Виртуальные функции - C++
Здравствуйте,уважаемые посетители форума.Пишу программу созданию фигур и их перемещению на экране использую виртуальные функции.И...

Виртуальные функции - C++
Объясните пожалуйста зачем нужны чисто виртуальные функции?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru