Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231

Наследование

19.08.2020, 15:16. Показов 2418. Ответов 33

Студворк — интернет-сервис помощи студентам
Потихоньку изучаю С++. Разбираю реализацию ООП на этом языке.
Сделал простенькие класса для понимания концепции наследования.

Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Person
{
protected:
    std::string _name;
    unsigned int _age;
 
public:
    Person(std::string name, unsigned int age ) : _name{name}, _age{age} {}
    virtual ~Person() = default;
 
    virtual void print() { std::cout << _name << _age << std::endl; }
};
 
class Professor : public Person
{
public:
    Professor(std::string name, unsigned int age) : Person{ name, age } {}
    virtual ~Professor() = default;
 
    void print() override { std::cout << "Prof " << _name << " " << _age << std::endl; }
};


Решил добавить к этому контейнеры. Создал ещё два класса.

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class House
{
public:
    virtual ~House() = default;
 
    virtual std::vector<Person*> get_person() { throw new std::exception("NotImplemented"); };
};
 
class University : public House
{
private:
    std::vector<Professor*> _professors;
public:
 
    std::vector<Person*> get_person() override{ return _professors; };
 
};

И тут началось. Не работает метод get_person() класса University. Не понимаю почему. dynamic_cast не помогает. Правда, я мб неправильно его использую? Делаю так
C++
1
dynamic_cast<std::vector<Person*>>(_professors)
. Что я делаю неправильно?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.08.2020, 15:16
Ответы с готовыми решениями:

Заменить наследование классов на наследование интерфейсов
#include &lt;iostream&gt; #include &lt;assert.h&gt; using namespace std; int people_on_base = 100; int vehicles_on_base = 100; double...

Наследование
Наследование 1)Должна быть табличка 3*3 2)Разные типы наследования 3)программа в в которой будет наследоваться клас 4) наследуются...

С++ Наследование
#include &lt;conio.h&gt; #include &lt;iostream.h&gt; class MyClass { int a; public: MyClass(int); show_a(int) ...

33
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
22.08.2020, 23:33
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от schoolboy_ Посмотреть сообщение
память в результирующем векторе будет выделяться при каждой вставке?
Вектор будет создаваться при каждом вызове этой функции. Но память под все элементы будет выделена сразу.

Цитата Сообщение от schoolboy_ Посмотреть сообщение
лучше создать результирующий вектор размером _professots.size() и туда скопировать по индексу?
Создание элемента в векторе уже подразумевает его инициализацию (и далее будет перезапись новым объектом старого). Чтоб этого не было, у вектора есть функция резервирования места под элементы (reserve), ей в подобных случаях и пользоваться (не будет лишнего создания элемента). Но не в этом.
1
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,518
23.08.2020, 16:30
Цитата Сообщение от DrOffset Посмотреть сообщение
Вы в функции ждете std::vector<Person*> & и передаете std::vector<Person*>.
А в примере с возвратом вы заявили тип std::vector<Person*>, но возвращаете по факту std::vector<Professor*>
подправила на своё усмотрение (для примера работающего)
Кликните здесь для просмотра всего текста
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
72
73
74
75
76
// https://www.cyberforum.ru/cpp-beginners/thread2690819.html
// Наследование 
 
#include <iostream>
#include <vector>
#include <exception>
 
class Person
{
protected:
    std::string _name;
    unsigned int _age;
 
public:
    Person(std::string name, unsigned int age ) : _name{name}, _age{age} {}
    virtual ~Person() = default;
 
    virtual void print() { std::cout << _name << _age << std::endl; }
};
 
class Professor : public Person
{
public:
    Professor(std::string name, unsigned int age) : Person{ name, age } {}
    virtual ~Professor() = default;
 
    void print() override { std::cout << "Prof " << _name << " " << _age << std::endl; }
};
 
class House
{
public:
    virtual ~House() = default;
 
    virtual std::vector<Person*> get_person() {};       //   throw std::exception("NotImplemented");  
    
};
 
 
class University : public House
{
    private:
        std::vector<Person*> _professors;
    public:
     
    //void add_professor(Person* professor) { _professors.push_back(professor); }
        
    // вернуть контейнер
    std::vector<Person*> get_person() override { 
            return std::vector<Person *>(_professors.begin(), _professors.end());
        }
     
    void f(std::vector<Person*>& persons)
        {
            for (auto person : persons)
                person->print();
        }
};
 
 
int main(int argc, const char *argv[])
{    
    Person* p = new Person("Oleg", 18);
    Person* prof = new Professor("Bjarne Stroustrup", 54);
     
    std::vector<Person*> persons(2);
    persons[0] = p;
    persons[1] = prof;
     
    // передача ссылки
    std::vector<Person*>& refP=persons;     
    University u;
    u.f(refP);
 
    return 0;
}

отдельно add_professor не вижу смысла в классе university
хотя с person'ами и прфессорами всё равно как-то туманно...
всё-таки add_person и add_professor ещё доработать бы
1
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
23.08.2020, 21:25  [ТС]
Цитата Сообщение от TRam_ Посмотреть сообщение
Создание элемента в векторе уже подразумевает его инициализацию (и далее будет перезапись новым объектом старого).
т.е. если я пишу так:

C++
1
std::vector<Person> persons(10);
то будет не просто зарезервирована память под десять элементов типа Person. Для каждого элемента будет вызван конструктор по-умолчанию?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
23.08.2020, 22:48
schoolboy_, да.

Добавлено через 5 минут
А вот так:
C++
1
2
std::vector<Person> persons;
persons.reserve(10);
будет зарезервирована память, но никаких конструкторов элементов не вызовется. Они (конструкторы копирования) вызовутся при push_back, а при emplace_back - конструкторы перемещения.
1
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
24.08.2020, 06:23  [ТС]
Что-то не сходится. Для Person и Professor нет конструктора по умолчанию. Так что будет вызывать компилятор?
0
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,518
24.08.2020, 07:53
Цитата Сообщение от schoolboy_ Посмотреть сообщение
Для Person и Professor нет конструктора по умолчанию. Так что будет вызывать компилятор?
ликбез
При создании объекта класса, который не содержит ни одного конструктора, будет вызываться неявно заданный конструктор по умолчанию (default constructor), выделяющий память для объекта класса. Однако, в классе можно объявить собственный конструктор по умолчанию. Такой конструктор называется: явно заданный конструктор по умолчанию.
Кликните здесь для просмотра всего текста
If I define the following class
class X
{};

The compiler will define the following methods:
X::X() {} // Default constructor. It takes zero arguments (hence default).
X::~X() {} // Destructor
X::X(X const& rhs) {}; // Copy constructor
X& operator=(X const& rhs)
{return *this;} // Assignment operator.

Note:
The default constructor is not built if ANY constructor is defined.
The other methods are not built if the user defines an alternative
и общим планом - Порядок вызова конструктора / деструктора в C ++
0
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
24.08.2020, 08:26  [ТС]
JeyCi, компилятор создаст конструктор по умолчанию, только если не задан не один конструктор? Но если пользователь задал конструктор сам, то компилятор ничего делать не будет. В классе Person и Professor есть пользовательские конструкторы.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
24.08.2020, 09:04
Цитата Сообщение от schoolboy_ Посмотреть сообщение
Что-то не сходится. Для Person и Professor нет конструктора по умолчанию. Так что будет вызывать компилятор?
Правильно говорить, что для элементов вектора осуществляется инициализация.
Инициализация в С++ может происходить не только посредством конструкторов.
1
3 / 3 / 1
Регистрация: 02.03.2013
Сообщений: 231
24.08.2020, 09:06  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Инициализация в С++ может происходить не только посредством конструкторов.
а как ещё?
и что в итоге будет генерировать компилятор глядя на такой код:
C++
1
std::vector<Person> persons(10)
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
24.08.2020, 09:10
Вот это
Цитата Сообщение от schoolboy_ Посмотреть сообщение
В классе Person и Professor есть пользовательские конструкторы.
и это
Цитата Сообщение от schoolboy_ Посмотреть сообщение
т.е. если я пишу так:
C++
1
std::vector<Person> persons(10);
то будет не просто зарезервирована память под десять элементов типа Person. Для каждого элемента будет вызван конструктор по-умолчанию?
просто даст ошибку компиляции, т.к. конструкторов по умолчанию у ваших классов нет.

Добавлено через 2 минуты
Цитата Сообщение от schoolboy_ Посмотреть сообщение
а как ещё?
Тут: https://en.cppreference.com/w/... ialization

В целом это сейчас не относится к теме. Я просто уточнил, что говорить в общем случае о конструкторах применительно к вектору не совсем корректно. Вектор выполняет инициализацию. Иногда она приводит к вызовам соответствующих конструкторов. Но, например, вектор из int никаких конструкторов не вызывает, по причине того, что у элементарных типов нет конструкторов. Вместо этого выполняется, например, zero-initialization.
1
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,518
24.08.2020, 13:59
как-то почище
Кликните здесь для просмотра всего текста
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
72
73
74
75
76
77
78
79
80
// https://www.cyberforum.ru/cpp-beginners/thread2690819.html
// Наследование 
 
#include <iostream>
#include <vector>
#include <exception>
 
class Person
{
protected:
    std::string _name;
    unsigned int _age;
 
public:
    Person(std::string name, unsigned int age ) : _name{name}, _age{age} {}
    virtual ~Person() = default;
 
    virtual void print() { std::cout << _name << " " <<  _age << std::endl; }
};
 
class Professor : public Person
{
public:
    Professor(std::string name, unsigned int age) : Person{ name, age } {}
    virtual ~Professor() = default;
 
    void print() override { std::cout << "Prof " << _name << " " << _age << std::endl; }
};
 
class House
{
public:
    virtual ~House() = default;
 
    virtual std::vector<Person*> get_person() {};       //   throw std::exception("NotImplemented");  
    
};
 
 
class University : public House
{
    private:
        std::vector<Person*> _stuff;
    //    int _sz;
    public:
     
    // int& getSize(){return _sz;}
     
    void add_person(Person* aPerson) { _stuff.push_back(aPerson); }
    
    void add_professor(Person* aProfessor) { _stuff.push_back(aProfessor); }
        
    // вернуть контейнер
    std::vector<Person*> get_person() override { 
            return std::vector<Person *>(_stuff.begin(), _stuff.end());
        }
        
    // print 
    void printAll() // std::vector<Person*>& persons
        {
            for (auto person : _stuff)
                person->print();
        }
};
 
 
int main(int argc, const char *argv[])
{       
    University u;
    
    Person* p = new Person("Oleg", 18);
    Person* prof = new Professor("Bjarne Stroustrup", 54);  
    Person* p2 = new Person("Nick", 18);
    u.add_person(p);
    u.add_person(p2);
    u.add_professor(prof);
    // вывод НАСЛЕДУЕТСЯ... 
    u.printAll();
    return 0;
}

но с деструктором ещё разобраться, наверно... т.к. всё-таки память выделяется... значит и delete надо задействовать... чтобы не было утечки памяти... и висячих указателей в данном случае
0
24.08.2020, 14:03

Не по теме:

Цитата Сообщение от JeyCi Посмотреть сообщение
"Bjarne Stroustrup", 54
Вы этот код 16 лет назад писали? :)

0
24.08.2020, 14:06

Не по теме:

я его у ТС'а взяла... теперь будем знать, когда у Stroustrup'а день рождения )) - см #32

0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
24.08.2020, 14:17
Цитата Сообщение от JeyCi Посмотреть сообщение
C++
1
2
3
4
    // вернуть контейнер
    std::vector<Person*> get_person() override { 
            return std::vector<Person *>(_stuff.begin(), _stuff.end());
        }
В этом необходимость отпадает, т.к. у вас в классе std::vector<Person *> хранится, а не std::vector<Professor *>.
Т.е. можно просто:
C++
1
2
3
    std::vector<Person*> get_person() override { 
            return _stuff;
        }
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.08.2020, 14:17
Помогаю со студенческими работами здесь

наследование
Пытаюсь разобраться в наследовании Есть класс class File { public: struct comp { char num; // Имя переменной char st;...

Наследование
На основе класса «Массив» создать производный класс «Ассоциативный массив». Данный класс содержит массив указателей, каждый из которых...

наследование
Задача : Базовый класс: class Shape2D { public: Shape2D(); virtual ~ Shape2D(); virtual float Area( )= 0; virtual...

Наследование
Реализовать наследование классов квартиры,этаж,подъезд,дом

Наследование
Суть задачи: Реализуйте класс символьная строка,наследуйте от него класс двоичная строка. Реализуйте методы Show(от базовой строки) ...


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

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru