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

Наследование и виртуальные функции - C++

Восстановить пароль Регистрация
 
qazc
0 / 0 / 1
Регистрация: 01.11.2011
Сообщений: 26
19.09.2013, 14:50     Наследование и виртуальные функции #1
Доброго времени суток. Есть два вопроса:

1) Подскажите, плиз, что делаю не так. Есть базовый класс human и класс наследник solder. Если вызывать методы setName и setAge из наследника solder, то они не будут работать. Почему?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class human {
    
    public: 
        void information() {
            cout << "My name is " << name << ". My age is " << age << endl;
        }
 
        void setAge(int set_age) {
            age = set_age;
        }
        
        void setName(string set_name) {
            name = set_name;
        }
    private:
        string name;
        int age;
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
class solder : public human {
        
    public: 
 
        void information() {
            cout << "I am solder! My name is " << name << " and my age is " << age << endl;
        }
        
    private:
        string name;
        int age;
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main() {
 
human *alex = new human;
 
alex->setName("Alex");
alex->setAge(25);
alex->information();
 
delete alex;
 
solder *ivan = new solder();
 
ivan->setName("Ivan");
ivan->setAge(20);
ivan->information();
 
delete ivan;
return 0;
}
Результат работы программы:
My name is Alex. My age is 25
I am solder! My name is and my age is 0


2) В классе наследнике функция information() перегружается и в итоге имеем другой результат для класса наследника. В чем тогда отличие между таким способом изменения результата в наследнике и если бы функция information() была объявлена как virtual в классе human и в наследнике была бы переопределена?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Cynacyn
 Аватар для Cynacyn
33 / 33 / 0
Регистрация: 02.05.2013
Сообщений: 109
19.09.2013, 15:02     Наследование и виртуальные функции #2
потому что вы не объявили их виртуальными
C++
1
virtual void information();

здесь:
C++
1
2
3
ivan->setName("Ivan");
ivan->setAge(20);
ivan->information();
вы меняет значения в базовом классе, потом выводите значения производного класса
m1Rr0r
 Аватар для m1Rr0r
247 / 230 / 15
Регистрация: 05.02.2010
Сообщений: 3,213
Завершенные тесты: 2
19.09.2013, 15:05     Наследование и виртуальные функции #3
конструктор есть где то ?
qazc
0 / 0 / 1
Регистрация: 01.11.2011
Сообщений: 26
19.09.2013, 15:17  [ТС]     Наследование и виртуальные функции #4
А чтобы использовать функции setName() и setAge() для класса наследника, то нужно их тоже объявить виртуальными и переопределить в наследнике?
Cynacyn
 Аватар для Cynacyn
33 / 33 / 0
Регистрация: 02.05.2013
Сообщений: 109
19.09.2013, 15:28     Наследование и виртуальные функции #5
В Вашем конкретном примере путаница вызвана тем, что в производном классе есть такие же данные члены, к которым в обращаетесь в information().
Имхо, дублирование данных лишнее, нужно просто убрать данные из производного класса и всё.

Цитата Сообщение от qazc Посмотреть сообщение
А чтобы использовать функции setName() и setAge() для класса наследника, то нужно их тоже объявить виртуальными и переопределить в наследнике?
если вы собираетесь их переопределять и/или использовать указатель на базовый класс, инициализированный указателем на производный класс, то функции нужно сделать виртуальными

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct st_base {
    virtual void display() { cout << "st_base::display()" << endl; }
    //void display() { cout << "st_base::display()" << endl; }
};
 
struct st_der : st_base {
    void display() { cout << "st_der::display()" << endl; }
};
 
int main () {
 
    st_base* pointer = new st_der;
    
    pointer->display(); }
вывод
st_der::display()
если сделать функцию display не виртуальной, то при обращении к указателю на базовый st_base, инициализированный указателем на производный st_der, будет вызывать display из базового st_base
qazc
0 / 0 / 1
Регистрация: 01.11.2011
Сообщений: 26
19.09.2013, 15:39  [ТС]     Наследование и виртуальные функции #6
Но мне не нужно переопределять эти два метода в производном классе, мне просто нужно их вызвать для производного класса и записать данные в него из ivan->SetName("...") и ivan->SetAge(...). Это можно как-то сделать используя унаследованные функции?

Цитата Сообщение от Cynacyn Посмотреть сообщение
В Вашем конкретном примере путаница вызвана тем, что в производном классе есть такие же данные члены, к которым в обращаетесь в information().
Имхо, дублирование данных лишнее, нужно просто убрать данные из производного класса и всё.
Если убрать данные для производного класса, то компилятор будет ругаться, что данные для базового класса являются скрытыми.
Cynacyn
 Аватар для Cynacyn
33 / 33 / 0
Регистрация: 02.05.2013
Сообщений: 109
19.09.2013, 17:52     Наследование и виртуальные функции #7
Цитата Сообщение от qazc Посмотреть сообщение
Но мне не нужно переопределять эти два метода в производном классе, мне просто нужно их вызвать для производного класса и записать данные в него из ivan->SetName("...") и ivan->SetAge(...). Это можно как-то сделать используя унаследованные функции?



Если убрать данные для производного класса, то компилятор будет ругаться, что данные для базового класса являются скрытыми.
Ваши унаследованные функции работают с данными членами базового (наследуемого) класса.
Чтобы компилятор не ругался, нужно в классе human данные члены объявить в разделе protected
C++
1
2
3
   protected:
        string name;
        int age;
данные объявленные в этом разделе доступны производному классу, как если бы они были объявлены в разделе public, для остальных пользователей эти данные закрыты
Cynacyn
 Аватар для Cynacyn
33 / 33 / 0
Регистрация: 02.05.2013
Сообщений: 109
24.09.2013, 14:50     Наследование и виртуальные функции #8
Цитата Сообщение от qazc Посмотреть сообщение
Доброго времени суток. Есть два вопроса:

2) В классе наследнике функция information() перегружается и в итоге имеем другой результат для класса наследника. В чем тогда отличие между таким способом изменения результата в наследнике и если бы функция information() была объявлена как virtual в классе human и в наследнике была бы переопределена?
Как я уже сказал, если бы инициализировали указатель на human (базовый) указателем на soldier (производный).
C++
1
2
human* p = new soldier;
p->information();
то при вызове метода information() (предполагается что он замещён в производном классе), вызывается метод soldier::information(), если в human метод information() объявлен как виртуальный, если нет - то тогда вызывается human::information().

+ ещё пример использования виртуальных функция из вики:
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
class A
{
public:
     virtual int function () {
        return 1;
     }
 
     int get() {
         return this->function();
     }
};
 
class B: public A
{
public:
     int function() {
        return 2;
     }
};
 
#include <iostream>
 
int main() {
   B b; 
 
   std::cout << b.get() << std::endl; // 2
 
   return 0;
}
rsdn: Зачем нужны виртуальные функции?

wiki: Виртуальные методы
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.09.2013, 15:32     Наследование и виртуальные функции
Еще ссылки по теме:

C++ Наследование и виртуальные функции
Наследование и виртуальные функции C++
Наследование и виртуальные функции C++

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

Или воспользуйтесь поиском по форуму:
qazc
0 / 0 / 1
Регистрация: 01.11.2011
Сообщений: 26
24.09.2013, 15:32  [ТС]     Наследование и виртуальные функции #9
Спасибо
Yandex
Объявления
24.09.2013, 15:32     Наследование и виртуальные функции
Ответ Создать тему
Опции темы

Текущее время: 01:18. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru