Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
1

Виртуальные функции.

27.07.2010, 15:26. Показов 1315. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Приветствую всех. Дана такая программа (на самом деле она больше и сложнее, но структура и проблема те же):

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
#include <iostream>
using namespace std;
 
class x1
    {
        public:
            virtual void show()
                {
                    cout << "1\n";
                }
    };
class x2 : public x1
    {
        public:
            void show()
                {
                    cout << "2\n";
                }
    };
 
class x3 : public x2
    {
        public:
            void show()
                {
                    cout << "3\n";
                }
    };
 
int main()
    {
        x1 *p[3];
 
        p[0] = &x1();
        p[1] = &x2();
        p[2] = &x3();
 
 
        for(int i = 0; i < 3; i++)
            {
                p[i]->show();
            }
        return 0;
    }
По идее она должна вывести 1 2 3 (на разных строках) но выводит 3 3 3... Вообще бред. Но если записать так

C++
1
2
3
4
5
6
p[0] = &x1();
p[0]->show();
p[1] = &x2();
p[1]->show();
p[2] = &x3();
p[2]->show();

то все ок. Я даже глупо переписал пример из самоучителя ! эффекта ноль. Теперь грешу на компилятор... Так в чем же дело...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.07.2010, 15:26
Ответы с готовыми решениями:

Виртуальные и чисто виртуальные функции
Чем они отличаются?? если можно, с примерами. И как из виртуальной функции сделать чисто...

Виртуальные функции
Разработать программу с использованием наследования классов, реализующую классы: Земноводное(ареал...

Виртуальные функции
Вопрос. Как вызвать функцию наследника через указатель на базовый класс? Так не компилируется...

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

18
2022 / 1621 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
27.07.2010, 15:40 2
Вы присваиваете указателям адреса временных объектов. Когда дело доходит до цикла, этих объектов уже не существует.
0
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 15:47  [ТС] 3
Но почему тогда выводится 3 3 3, а не еще что-нибудь...
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
27.07.2010, 16:04 4
Эм. Выводит 1, 2, 3 по вашему коду.
0
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 16:08  [ТС] 5
Что за компилятор??

Запустите кто-нибудь эту прогу и скажите что у вас выводит...
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
27.07.2010, 16:10 6
maxibon, IDE Visual Studio 2005.
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
27.07.2010, 16:12 7
Цитата Сообщение от Lavroff Посмотреть сообщение
Эм. Выводит 1, 2, 3 по вашему коду.
Аналогично. Может быть, приведешь уже весь код?
А вообще rangerx прав, и нужно бы сделать так (особенно, если классы у тебя имеют данные-члены):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
    x1 *p[3];
    p[0] = new x1;
    p[1] = new x2;
    p[2] = new x3;
 
    for(int i = 0; i < 3; i++)
        p[i]->show();
 
    for(size_t i = 0; i < 3; ++i)
        delete p[i];
    system("pause");
    return 0;
}
0
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 16:14  [ТС] 8
Цитата Сообщение от Lavroff Посмотреть сообщение
maxibon, IDE Visual Studio 2005.
это не компилятор а среда разработки// ладно, попробую зпускать show без цикла, а сразу после присваивания ему объекта. Всеи кто ответил спасибо1
0
ForEveR
27.07.2010, 16:16
  #9

Не по теме:

maxibon, А IDE я просто так перед названием написал да?) Я знаю, что это среда разработки)

0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
27.07.2010, 16:19 10
Цитата Сообщение от maxibon Посмотреть сообщение
Но почему тогда выводится 3 3 3, а не еще что-нибудь...
А может выводить хоть "Hello, World!", если заблагорассудится. Временных объектов уже не существует, а обращение (по указателю) к несуществующему объекту - это UB. Как именно это UB проявится - это Б.Г. его знает....
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
27.07.2010, 16:29 11
Цитата Сообщение от maxibon Посмотреть сообщение
ладно, попробую зпускать show без цикла, а сразу после присваивания ему объекта. Всеи кто ответил спасибо1
Это ничего не изменит, т.к. ты инициализируешь указатели временными объектами, которые уничтожаются сразу после инициализации.
0
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 16:36  [ТС] 12
Цитата Сообщение от Nameless One Посмотреть сообщение
Это ничего не изменит, т.к. ты инициализируешь указатели временными объектами, которые уничтожаются сразу после инициализации.
Самое интересное что изменит. Я ж еще этот вариант

C++
1
2
3
4
5
6
p[0] = &x1();
p[0]->show();
p[1] = &x2();
p[1]->show();
p[2] = &x3();
p[2]->show();
в самом первом посте написал. Ну и потом как ты объяснишь то что этот вариант

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
    {
        x1 *p[3];
 
        p[0] = &x1();
        p[1] = &x2();
        p[2] = &x3();
 
 
        for(int i = 0; i < 3; i++)
            {
                p[i]->show();
            }
        return 0;
    }
у некоторых работает?
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
27.07.2010, 16:45 13
Как сказал CheshireCat, поведение твоей программы не определено, о чем уже говорит то, что не у всех твой вариант работает. Согласись, правильно написанная программа должна работать у всех и всегда.
Пойми, что так делать - неправильно. Если ты будешь использовать в дальнейшем такой "трюк", то неприменно столкнешься с ошибками.

Цитата Сообщение от maxibon Посмотреть сообщение
Самое интересное что изменит
Опять-таки повторюсь:
Цитата Сообщение от Nameless One Посмотреть сообщение
ты инициализируешь указатели временными объектами, которые уничтожаются сразу после инициализации
, поэтому не имеет значения, когда ты будешь вызывать свою функцию. Потому, что:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
    {
        x1 *p[3];
 
        p[0] = &x1();
        p[1] = &x2();//Здесь УЖЕ не существует объекта, адрес которого ты присвоил p[0]
        p[2] = &x3();
 
 
        for(int i = 0; i < 3; i++)
            {
                p[i]->show();//Как и не существует этого объекта здесь
            }
        return 0;
    }
В общем, дело твое, делай как хочешь, но мы тебя предупредили...
1
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
27.07.2010, 21:26 14
А поясните, пожалуйста, что означает конструкция

C++
1
p[0] = &x1();
конструктор вроде бы как нельзя вызывать напрямую
0
Эксперт С++
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
28.07.2010, 06:45 15
Evg, здесь создается временный (безымянный) объект типа x1 (при этом вызывается конструктор по умолчанию для временного объекта), и его адрес присваивается указателю на x1. Но соль в том, что после присваивания адреса временный объект уничтожается, и указатель хранит адрес уже не существующего объекта.
Вот пример того, как можно было бы использовать временные объекты:
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
#include <iostream>
#include <string>
 
#define print(A) std::cout << #A " = \"" << A << "\"" << std::endl
 
class abc
{
    std::string msg;
public:
    abc()
        : msg("Hello, World")
    {}
    abc(const abc& rhs)
        : msg(rhs.msg)
    {}
    friend std::ostream& operator << (std::ostream& os, const abc& rhs)
    {
        os << rhs.msg;
        return os;
    }
};
 
int main()
{
    std::string string1 = std::string("test");
    std::string string2 = std::string(string1);
    int x = int();
    abc a = abc();
 
    print(string1);
    print(string2);
    print(x);
    print(a);
    system("pause");
    return EXIT_SUCCESS;
}
1
Эксперт С++
2347 / 1720 / 148
Регистрация: 06.03.2009
Сообщений: 3,675
28.07.2010, 09:30 16
Цитата Сообщение от maxibon Посмотреть сообщение
у некоторых работает?
То что ты написал, как было сказано выше, приводит к UB. Это означает что поведение твоей программы неопределено и будет зависеть от используемого компилятора. Например такой код (не сильно от твоего отличающийся) прекрасно работает в MSVS:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
 
class Zombi {
public:
  virtual void Say() {
    std::cout << "I'm zombi" << std::endl;
  }
};
 
int main() {
  ((Zombi*)0)->Say();
 
  return 0;
}
А на codepad.org (g++ 4.1.2) нет: http://codepad.org/Bjt6ns3i. Твой вариант не компилится вообще.
Поэтому вместо того, чтобы спорить, прислушайся к тому, что было сказано выше.
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
28.07.2010, 13:09 17
Цитата Сообщение от Nameless One Посмотреть сообщение
Evg, здесь создается временный (безымянный) объект типа x1 (при этом вызывается конструктор по умолчанию для временного объекта)
Всё, наконец допёрло. Это ж не вызов конструктора, а создание экземпляра класса на лету. Моя тормоз

Цитата Сообщение от Nameless One Посмотреть сообщение
Но соль в том, что после присваивания адреса временный объект уничтожается, и указатель хранит адрес уже не существующего объекта
Это понятно. Мне непонятна была лишь конструкция языка.
0
34 / 34 / 8
Регистрация: 07.06.2010
Сообщений: 118
28.07.2010, 16:50 18
Я про временные обьекты первый раз прочиталО_о
После чего уничтожаются временные обьеты ? в википедии написано
уничтожаются сразу же, как только в них исчезает потребность
когда исчезает потребность ?
0
Evg
Эксперт CАвтор FAQ
21279 / 8301 / 637
Регистрация: 30.03.2009
Сообщений: 22,659
Записей в блоге: 30
28.07.2010, 16:55 19
Объекты должны уничтожаться по завершению statement'а. В данном случае - грубо говоря по достижению ";"
1
28.07.2010, 16:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.07.2010, 16:55
Помогаю со студенческими работами здесь

Виртуальные функции
Создать абстрактный базовый класс с виртуальной функцией - объем. Создать производные классы:...

Виртуальные функции
На основе базового класса Страна (3 поля) создать дочерние классы Республика и Монархия(по 2 поля)....

виртуальные функции
сделать какой либо из методов класса виртуальным #include&lt;iostream.h&gt; #include&lt;stdio.h&gt; class...

Виртуальные функции
Создать базовый класс «работник больницы» и производные классы «медсестра», «хирург». Выведите на...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru