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

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

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

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

03.01.2014, 00:17. Просмотров 1011. Ответов 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;
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.01.2014, 00:17
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Разница между виртуальным и простым методом (C++):

В чем разница между простым линейным списком, и динамическим линейным списком? - C++
вопрос в теме

Что не так с виртуальным методом - C++
class OperationBehavior{ virtual TMMatrix calc(); }; class GaussianInverse: public OperationBehavior { TMMatrix...

можно объявлять конкретный класс с чисто виртуальным методом - C++
можно объявлять конкретный класс с чисто виртуальным методом

Сформировать набор классов связанных между собой виртуальным наследованием,описать каждый класс - C++
Сформировать набор классов связанных между собой виртуальным наследованием,описать каждый класс

Разница между != и <= - C++
Здравствуйте! Писал программу с использованием QuickSort и заинтересовала такая вещь: void quickSort(int arr, int left, int right) { ...

Разница между 0 и 00 ? - C++
Как заставить программу различать 0 и 00 (ноль и два ноля, как в рулетке)? Вариант с заменой 00 на какое-то число не подходит, так как...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
alsav22
5420 / 4816 / 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;
Почитайте про полиморфизм.
1
Jack Wade
63 / 36 / 6
Регистрация: 24.02.2013
Сообщений: 250
03.01.2014, 00:30  [ТС] #3
alsav22, спасибо конечно, но что то я не могу понять суть...
Почему, когда идёт обращение именно через указатель-виртуальная функция переопределяется, а обычная-нет, а когда обращается напрямую через сами переменные, а не указатели, то тогда разницы нету?
Можете вкраце пояснить, если не затруднит?
0
alsav22
5420 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.01.2014, 00:40 #4
Цитата Сообщение от Jack Wade Посмотреть сообщение
Почему, когда идёт обращение именно через указатель-виртуальная функция переопределяется, а обычная-нет, а когда обращается напрямую через сами переменные, а не указатели, то тогда разницы нету?
Потому что так сделано. В этом и есть полиморфизм - указатель одного типа, а поведение разное. Только не
функция переопределяется
, а вызывается метод того класса, с которым связан указатель (вызов по типу объекта, а не по типу указателя).
1
MrGluck
Модератор
Эксперт CЭксперт С++
7239 / 4407 / 642
Регистрация: 29.11.2010
Сообщений: 11,929
03.01.2014, 01:55 #5
На мой взгляд, самое доступное и простое объяснение, которое все делает прозрачно:
виртуальная функция указывает на то, что у функции надо наследовать объявление и реализацию по-умолчанию.
чисто виртуальная функция указывает на то, что у функции надо наследовать объявление,
обычная функция --|| -- объявление и реализацию.

А понять весь механизм легче всего при использовании полиморфизма с указателем на базовый класс, который показывает на объект типа производного класса.
1
Jack Wade
63 / 36 / 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;
}
0
alsav22
5420 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
03.01.2014, 03:04 #7
Цитата Сообщение от Jack Wade Посмотреть сообщение
я не могу понять толком, по какой причине, указатель на класс one спокойно видит адрес на класс two...
Цитата Сообщение от alsav22 Посмотреть сообщение
Потому что так сделано.
Ссылка или указатель на базовый класс может быть связана и с объектом производного класса, без явного преобразования типов.
1
outoftime
║XLR8║
510 / 432 / 33
Регистрация: 25.07.2009
Сообщений: 2,295
03.01.2014, 03:23 #8
http://www.learncpp.com/cpp-tutorial...virtual-table/ вот учебник о том что такое virtual table.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.01.2014, 03:23
Привет! Вот еще темы с ответами:

Разница между С и С++ - C++
Если не брать во внимание объекты и классы, то разница состоит только лишь в cin, cout и директивах?

Разница между if else и else if - C++
Привет, у меня возник &quot;нубский&quot; вопрос. Этот код, это же соркащенная версия нижнего? int i = 3; if (i == 1) ...

Разница между T **a и T *a[const_size] - C++
T c_a; // Здесь тип c_a это T(*) T **d_a = (T**) malloc(sizeof(T) * size); for (i = 0; i &lt; size; ++i) { d_a = (T*)...

В чем разница между [] и * ? - C++
Думал, что ни в чем, но когда попытался сделать так: (в файле 1) char lc; в файле 2: extern char* lc; Компилятор ругаться не стал,...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
03.01.2014, 03:23
Ответ Создать тему
Опции темы

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