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

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

Войти
Регистрация
Восстановить пароль
 
Jack Wade
62 / 35 / 6
Регистрация: 24.02.2013
Сообщений: 250
#1

Разница между виртуальным и простым методом - C++

03.01.2014, 00:17. Просмотров 860. Ответов 7
Метки нет (Все метки)

Здравствуйте!
Подскажите пожалуйста...
Я прочитал про виртуальные методы в классах, и, как было описано, что виртуальные методы служат для того, чтобы можно было переопределить функцию(метод) из класса наследника(допустим, есть класс one, в нём есть функция fun_1, она возвращает(просто возвращает) int 1992, и есть класс two, который является наследником класса one, в нём переопределяем функцию, дабы она вернула значение уже 24, функция fun_1 подписана, как виртуальная, так же есть функция fun_2, она, так же, как и fun_1, просто возвращает число, только 2014, а её переопределение в классе two возвращает 15).
После всех переопределений, когда я запускаю программу, дабы увидеть результат и разницу между виртуальным и простым методом... Разницы-нету. Переопределились оба метода, и с virtual, и без virtual... Смотрел в примере, взятым из Википедии, по описанию примера-всё правильно, однако, вот такой результат...
Вот код:
Кликните здесь для просмотра всего текста

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
#include "stdafx.h"
#include <stdio.h>
 
class one
{
    public: virtual int fun_1(void) { return 1992; };
    public:         int fun_2(void) { return 2014; };
};
 
class two : public one
{
    public: virtual int fun_1(void) { return 24; };
    public:         int fun_2(void) { return 15; };
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    one x;
    two y;
    printf("CLASS_ONE:\n");
    printf("%d\n", x.fun_1());
    printf("%d\n", x.fun_2());
    printf("CLASS_TWO:\n");
    printf("%d\n", y.fun_1());
    printf("%d\n", y.fun_2());
    _gettch();
    return 0;
}

Подскажите пожалуйста, что я делаю не так... И раз оба метода у меня переопределились-в чём тогда вообще смысл виртуальных методов(если не затруднит)?
Вот ещё, ради интереса сделал для себя другой пример, полностью повторяющий пример из Википедии, только их пример, почему то и в правду, не переопределяет не виртуальный метод, в отличии от моего...
Кликните здесь для просмотра всего текста

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
#include "stdafx.h"
#include <stdio.h>
 
class one
{
    public: virtual void fun_1(void) { printf("one::fun_1()\n"); };
    public:         void fun_2(void) { printf("one::fun_2()\n"); };
};
 
class two : public one
{
    public: virtual void fun_1(void) { printf("two::fun_1()\n"); };
    public:         void fun_2(void) { printf("two::fun_2()\n"); };
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    one* _one=new one;
    two* _two=new two;
    _one->fun_1();
    _one->fun_2();
    _two->fun_1();
    _two->fun_2();
    _gettch();
    delete _one;
    delete _two;
    return 0;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5415 / 4811 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.01.2014, 00:25     Разница между виртуальным и простым методом #2
Цитата Сообщение от Jack Wade Посмотреть сообщение
После всех переопределений, когда я запускаю программу, дабы увидеть результат и разницу между виртуальным и простым методом... Разницы-нету.
Вот так сделайте и увидите разницу:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
one x;
   two y;
    
    one* p;
    p = &x;
    printf("CLASS_ONE:\n");
    printf("%d\n", p ->fun_1());
    printf("%d\n", p ->fun_2());
    
    p = &y;
    printf("CLASS_TWO:\n");
    printf("%d\n", p ->fun_1());
    printf("%d\n", p ->fun_2());
    
    _gettch();
    return 0;
Почитайте про полиморфизм.
Jack Wade
62 / 35 / 6
Регистрация: 24.02.2013
Сообщений: 250
03.01.2014, 00:30  [ТС]     Разница между виртуальным и простым методом #3
alsav22, спасибо конечно, но что то я не могу понять суть...
Почему, когда идёт обращение именно через указатель-виртуальная функция переопределяется, а обычная-нет, а когда обращается напрямую через сами переменные, а не указатели, то тогда разницы нету?
Можете вкраце пояснить, если не затруднит?
alsav22
5415 / 4811 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.01.2014, 00:40     Разница между виртуальным и простым методом #4
Цитата Сообщение от Jack Wade Посмотреть сообщение
Почему, когда идёт обращение именно через указатель-виртуальная функция переопределяется, а обычная-нет, а когда обращается напрямую через сами переменные, а не указатели, то тогда разницы нету?
Потому что так сделано. В этом и есть полиморфизм - указатель одного типа, а поведение разное. Только не
функция переопределяется
, а вызывается метод того класса, с которым связан указатель (вызов по типу объекта, а не по типу указателя).
MrGluck
Ворчун
Эксперт CЭксперт С++
6634 / 3825 / 502
Регистрация: 29.11.2010
Сообщений: 10,110
03.01.2014, 01:55     Разница между виртуальным и простым методом #5
На мой взгляд, самое доступное и простое объяснение, которое все делает прозрачно:
виртуальная функция указывает на то, что у функции надо наследовать объявление и реализацию по-умолчанию.
чисто виртуальная функция указывает на то, что у функции надо наследовать объявление,
обычная функция --|| -- объявление и реализацию.

А понять весь механизм легче всего при использовании полиморфизма с указателем на базовый класс, который показывает на объект типа производного класса.
Jack Wade
62 / 35 / 6
Регистрация: 24.02.2013
Сообщений: 250
03.01.2014, 02:59  [ТС]     Разница между виртуальным и простым методом #6
MrGluck, alsav22, большое Вам спасибо!
Я немного уже начинаю конечно понимать, однако, не совсем уверен, что правильно...
Поправьте пожалуйста, если я не прав:
Как я понимаю, при наследовании классом one класса two, мы просто получаем указатель на сам экземпляр класса one в класс two, и ссылки на методы у нас переопределить-невозможно. Однако, при использовании virtual метода, изменении ссылки допускается, и теперь, при использовании указателя на класс, мы получаем не ссылку на метод первого класса, а ссылку на метод второго класса(иными словами-при использовании указателей, методы fun_1 и fun_2, без использования virtual, мы бы вызывали методы из экземпляра класса one, т.е. они не были бы переопределены, а при использовании virtual, в случае, если в классе two есть метод fun_1, то впервую очередь, будет вызван именно метод fun_1 из второго класса, т.е. ссылка будет указывать не на метод первого класса, а на метод второго класса)...
Ну, я так это вижу... Может-неправильно(да, и скорее всего, так и есть), но, я так понял понял, читая информацию с различных источников...

Добавлено через 6 минут
Я вот только одного не могу понять:
Вот мы объявляем ссылку на класс one, для примера, и присваиваем её адресу на класс one(переменная Х, для примера, являющаяся переменной типа нашего класса).
Мы её используем, как ни в чём не бывало, однако, когда мы присваиваем ссылку на класс one адресу на класс two, компилятор не ругается, хотя, казалось бы, это разные классы, и это ошибка...
Я конечно подозреваю, что это связано с наследованием класса two класса one, однако, я не могу понять толком, по какой причине, указатель на класс one спокойно видит адрес на класс two...
Если можно-объясните пожалуйста...

Добавлено через 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
#include "stdafx.h"
#include <stdio.h>
 
class one
{
    public: virtual void fun_1(void) { printf("one::fun_1()\n"); };
    public:         void fun_2(void) { printf("one::fun_2()\n"); };
 
class two : public one
{
    public: virtual void fun_1(void) { printf("two::fun_1()\n"); };
    public:         void fun_2(void) { printf("two::fun_2()\n"); };
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    one x;
    two y;
    one* pointer=&x;
    printf("===\nORIGINAL FUNCTIONS:\n===\n");
    printf("CLASS_ONE:\n");
    x.fun_1();
    x.fun_2();
    printf("CLASS_TWO:\n");
    y.fun_1();
    y.fun_2();
    printf("===\nPOINTER FUNCTIONS:\n===\n");
    printf("CLASS_ONE:\n");
    pointer->fun_1();
    pointer->fun_2();
    printf("CLASS_TWO:\n");
    pointer=&y;
    pointer->fun_1();
    pointer->fun_2();
    _gettch();
    delete pointer;
    return 0;
}
alsav22
5415 / 4811 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.01.2014, 03:04     Разница между виртуальным и простым методом #7
Цитата Сообщение от Jack Wade Посмотреть сообщение
я не могу понять толком, по какой причине, указатель на класс one спокойно видит адрес на класс two...
Цитата Сообщение от alsav22 Посмотреть сообщение
Потому что так сделано.
Ссылка или указатель на базовый класс может быть связана и с объектом производного класса, без явного преобразования типов.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.01.2014, 03:23     Разница между виртуальным и простым методом
Еще ссылки по теме:

C++ Разница между С и С++
можно объявлять конкретный класс с чисто виртуальным методом C++
C++ Разница между DEV и VS
Разница между if else и else if C++
Сформировать набор классов связанных между собой виртуальным наследованием,описать каждый класс C++

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

Или воспользуйтесь поиском по форуму:
outoftime
║XLR8║
506 / 428 / 33
Регистрация: 25.07.2009
Сообщений: 2,295
03.01.2014, 03:23     Разница между виртуальным и простым методом #8
http://www.learncpp.com/cpp-tutorial...virtual-table/ вот учебник о том что такое virtual table.
Yandex
Объявления
03.01.2014, 03:23     Разница между виртуальным и простым методом
Ответ Создать тему
Опции темы

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