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

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

Восстановить пароль Регистрация
 
maxibon
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 15:26     Виртуальные функции. #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
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();

то все ок. Я даже глупо переписал пример из самоучителя ! эффекта ноль. Теперь грешу на компилятор... Так в чем же дело...
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.07.2010, 15:26     Виртуальные функции.
Посмотрите здесь:

C++ Виртуальные функции
C++ Виртуальные функции
C++ виртуальные функции
C++ виртуальные и чисто виртуальные функции
Виртуальные функции C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
rangerx
1908 / 1517 / 139
Регистрация: 31.05.2009
Сообщений: 2,876
27.07.2010, 15:40     Виртуальные функции. #2
Вы присваиваете указателям адреса временных объектов. Когда дело доходит до цикла, этих объектов уже не существует.
maxibon
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 15:47  [ТС]     Виртуальные функции. #3
Но почему тогда выводится 3 3 3, а не еще что-нибудь...
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
27.07.2010, 16:04     Виртуальные функции. #4
Эм. Выводит 1, 2, 3 по вашему коду.
maxibon
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 16:08  [ТС]     Виртуальные функции. #5
Что за компилятор??

Запустите кто-нибудь эту прогу и скажите что у вас выводит...
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
27.07.2010, 16:10     Виртуальные функции. #6
maxibon, IDE Visual Studio 2005.
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
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;
}
maxibon
0 / 0 / 0
Регистрация: 27.07.2010
Сообщений: 7
27.07.2010, 16:14  [ТС]     Виртуальные функции. #8
Цитата Сообщение от Lavroff Посмотреть сообщение
maxibon, IDE Visual Studio 2005.
это не компилятор а среда разработки// ладно, попробую зпускать show без цикла, а сразу после присваивания ему объекта. Всеи кто ответил спасибо1
ForEveR
27.07.2010, 16:16
  #9

Не по теме:

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

CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,308
27.07.2010, 16:19     Виртуальные функции. #10
Цитата Сообщение от maxibon Посмотреть сообщение
Но почему тогда выводится 3 3 3, а не еще что-нибудь...
А может выводить хоть "Hello, World!", если заблагорассудится. Временных объектов уже не существует, а обращение (по указателю) к несуществующему объекту - это UB. Как именно это UB проявится - это Б.Г. его знает....
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
27.07.2010, 16:29     Виртуальные функции. #11
Цитата Сообщение от maxibon Посмотреть сообщение
ладно, попробую зпускать show без цикла, а сразу после присваивания ему объекта. Всеи кто ответил спасибо1
Это ничего не изменит, т.к. ты инициализируешь указатели временными объектами, которые уничтожаются сразу после инициализации.
maxibon
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;
    }
у некоторых работает?
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
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;
    }
В общем, дело твое, делай как хочешь, но мы тебя предупредили...
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,132
Записей в блоге: 26
27.07.2010, 21:26     Виртуальные функции. #14
А поясните, пожалуйста, что означает конструкция

C++
1
p[0] = &x1();
конструктор вроде бы как нельзя вызывать напрямую
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
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;
}
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2293 / 1663 / 86
Регистрация: 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. Твой вариант не компилится вообще.
Поэтому вместо того, чтобы спорить, прислушайся к тому, что было сказано выше.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,132
Записей в блоге: 26
28.07.2010, 13:09     Виртуальные функции. #17
Цитата Сообщение от Nameless One Посмотреть сообщение
Evg, здесь создается временный (безымянный) объект типа x1 (при этом вызывается конструктор по умолчанию для временного объекта)
Всё, наконец допёрло. Это ж не вызов конструктора, а создание экземпляра класса на лету. Моя тормоз

Цитата Сообщение от Nameless One Посмотреть сообщение
Но соль в том, что после присваивания адреса временный объект уничтожается, и указатель хранит адрес уже не существующего объекта
Это понятно. Мне непонятна была лишь конструкция языка.
[Freeman]
34 / 34 / 6
Регистрация: 07.06.2010
Сообщений: 118
28.07.2010, 16:50     Виртуальные функции. #18
Я про временные обьекты первый раз прочиталО_о
После чего уничтожаются временные обьеты ? в википедии написано
уничтожаются сразу же, как только в них исчезает потребность
когда исчезает потребность ?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.07.2010, 16:55     Виртуальные функции.
Еще ссылки по теме:

Виртуальные функции C++
виртуальные функции C++
Виртуальные функции C++

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

Или воспользуйтесь поиском по форуму:
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,132
Записей в блоге: 26
28.07.2010, 16:55     Виртуальные функции. #19
Объекты должны уничтожаться по завершению statement'а. В данном случае - грубо говоря по достижению ";"
Yandex
Объявления
28.07.2010, 16:55     Виртуальные функции.
Ответ Создать тему
Опции темы

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