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

Виртуальное наследование (указатель на базовый класс) - C++

Восстановить пароль Регистрация
 
akk
 Аватар для akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
15.05.2013, 23:27     Виртуальное наследование (указатель на базовый класс) #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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
class C1
{
protected:
    int a;
public:
    C1():a(1){std::cout << "Konstructor C1\n";}
    ~C1(){std::cout << "Destructor C1\n";}
    int Get1();
};
class C2: virtual public C1
{
protected:
    int b;
public:
    C2():b(2){std::cout << "Konstructor C2\n";}
    ~C2(){std::cout << "Destructor C2\n";}
    int Get2();
};
class C3: virtual public C1
{
protected:
    int c;
public:
    C3():c(3){std::cout << "Konstructor C3\n";}
    ~C3(){std::cout << "Destructor C3\n";}
    int Get3();
};
class C4: public C1
{
protected:
    int d;
public:
    C4():d(4){std::cout << "Konstructor C4\n";}
    ~C4(){std::cout << "Destructor C4\n";};
    int Get4();
    
};
 
using namespace std;
int main()
{
    C1 * pointer;
    pointer = new C4();
    cout << pointer->Get4();
 
 
    return 0;
}
int C1::Get1()
{
    return a;
}
int C2::Get2()
{
    return b;
}
int C3::Get3()
{
    return c;
}
int C4::Get4()
{
    return d;
}
Компилятор выдает ошибку class C1 has no member named Get4
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
stima
429 / 284 / 16
Регистрация: 22.03.2011
Сообщений: 923
Завершенные тесты: 1
15.05.2013, 23:32     Виртуальное наследование (указатель на базовый класс) #2
Используете множественное наследование, хотя не знаете что такое обычное наследование. (Это ответ)
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
15.05.2013, 23:32     Виртуальное наследование (указатель на базовый класс) #3
C++
1
2
3
C1* pointer;  // статический тип - указатель на С1
pointer = new C4();
cout << pointer->Get4(); // вызов метода через указатель, чей статический тип - C1*, в котором нет метода Get4()
akk
 Аватар для akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
15.05.2013, 23:42  [ТС]     Виртуальное наследование (указатель на базовый класс) #4
Все равно если заменить 29 строку на class C4: public C2, public C3
не работает.
DU, а как сделать чтобы можно было так вызывать метод
stima
429 / 284 / 16
Регистрация: 22.03.2011
Сообщений: 923
Завершенные тесты: 1
15.05.2013, 23:46     Виртуальное наследование (указатель на базовый класс) #5
Прочитайте что такое наследование.
akk
 Аватар для akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
15.05.2013, 23:49  [ТС]     Виртуальное наследование (указатель на базовый класс) #6
stima, да я читал про обыкновенное наследование, а тут множественное, хочу разобраться в этом, можете подсказать?
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
15.05.2013, 23:53     Виртуальное наследование (указатель на базовый класс) #7
Где множественное? Я не вижу у Вас классов которые имеют более одного родителя.
Кстати, в классе С1 надо сделать деструктор виртуальным, а то деструктор производного класса не вызывается.
stima
429 / 284 / 16
Регистрация: 22.03.2011
Сообщений: 923
Завершенные тесты: 1
15.05.2013, 23:55     Виртуальное наследование (указатель на базовый класс) #8
Цитата Сообщение от akk Посмотреть сообщение
stima, да я читал про обыкновенное наследование, а тут множественное, хочу разобраться в этом, можете подсказать?
Читали?) Напишите то что Вы хотите для 2 классов.
akk
 Аватар для akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
16.05.2013, 00:01  [ТС]     Виртуальное наследование (указатель на базовый класс) #9
Цитата Сообщение от stima Посмотреть сообщение
Напишите то что Вы хотите для 2 классов.
я хочу чтобы созданный указатель базового класса с1 и инициализированного через с4, можно было вызывать все методы, которые есть сейчас в классах
Olivеr, даже если добавить virtual ~C1() все равно не работает
stima
429 / 284 / 16
Регистрация: 22.03.2011
Сообщений: 923
Завершенные тесты: 1
16.05.2013, 00:03     Виртуальное наследование (указатель на базовый класс) #10
Напишите это кодом для 2 классов один наследуеться од другого
Psilon
Master of Orion
 Аватар для Psilon
5737 / 4685 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
16.05.2013, 00:04     Виртуальное наследование (указатель на базовый класс) #11
Да видно же, человек делает по методе даже не задумываясь о том, что делает.
stima
429 / 284 / 16
Регистрация: 22.03.2011
Сообщений: 923
Завершенные тесты: 1
16.05.2013, 00:06     Виртуальное наследование (указатель на базовый класс) #12
Так вот я и пытаюсь добиться что-бы человек прочитал внимательней)
akk
 Аватар для akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
16.05.2013, 00:08  [ТС]     Виртуальное наследование (указатель на базовый класс) #13
stima, все методы в С1 должны быть чисто виртуальными?
Psilon
Master of Orion
 Аватар для Psilon
5737 / 4685 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
16.05.2013, 00:10     Виртуальное наследование (указатель на базовый класс) #14
stima, Наивно

akk, подсказка: чтобы вызвать полиморфный метод, используя указатель базового класса на объект производного класса, всеравно необходимо, чтобы в базовом классе этот метод существовал. Вы написали
C++
1
2
C1 *c1 = new C4();
c1->Get4(); //ошибка. в классе C1 НЕТУ метода Get4, а компилятор _не знает_, что на самом деле это C4, он считает его C1
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
16.05.2013, 00:18     Виртуальное наследование (указатель на базовый класс) #15
akk, Не ну старина я от щас точно не помню, но вроде виртуальное наследование применяется, чтобы в самом нижнем классе был всего один объект базового класса, то есть чтобы не было неоднозначности. Я щас даже не представлю как это, но я вижу что у тебя в классах нету ни одной виртуальной функции, так что можешь спокойно просто делать наследование без 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
class C1
{
protected:
    int a;
public:
    C1():a(1){std::cout << "Konstructor C1\n";}
    ~C1(){std::cout << "Destructor C1\n";}
    virtual int Get();
};
class C2: virtual public C1
{
protected:
    int b;
public:
    C2():b(2){std::cout << "Konstructor C2\n";}
    ~C2(){std::cout << "Destructor C2\n";}
    virtual int Get();
};
class C3: virtual public C1
{
protected:
    int c;
public:
    C3():c(3){std::cout << "Konstructor C3\n";}
    ~C3(){std::cout << "Destructor C3\n";}
    virtual int Get();
};
class C4: public C2,public C3
{
protected:
    int d;
public:
    C4():d(4){std::cout << "Konstructor C4\n";}
    ~C4(){std::cout << "Destructor C4\n";};
    virtual int Get();
    
};
 
using namespace std;
int main()
{
    C1 * pointer;
    pointer = new C4();
    cout << pointer->Get();
    cout <<endl;
 
 
    return 0;
}
int C1::Get()
{
    return a;
}
int C2::Get()
{
    return b;
}
int C3::Get()
{
    return c;
}
int C4::Get()
{
    return d;
}
А еще поговорим о наследовании без virtual public, а просто public, что же у нас тогда происходит? Как я выше писал неоднозначность в самом нижнем классе должно быть два объекта самого верхнего базового класса в данном случае С1. Я честно сразу не понял почему неоднозначность, но щас догадался. Наверно потому, что С1 является также базовым классом и для C4, а там при наследовании без virtual хранится два объекта С1 и наверно механизм виртуальных функций не знает какой объект выбрать, чтобы вызвать функцию или C1::C2 или C1::C3, а если с virtual, то там всего один объект C1 оказывается и поэтому можно сделать виртуальный вызов. Просто других ответов я не вижу как еще это можно объяснить, да еще и в книге, вроде так как то написано.

Меня от еще мучает вопрос, а если построить ромб из 6 классов, в самом нижнем классе также будет один экземпляр базового класса? Просто лень тестить. По идее должен быть один. Если да тогда можно додумать, что виртуальное наследование применяется только для верхних классов. Ну в общем тестить нада, просто интересно. Если понял что я имею введу можешь протестить как оно будет. Ну или щас я попробую.

Добавлено через 15 секунд
akk, Не ну старина я от щас точно не помню, но вроде виртуальное наследование применяется, чтобы в самом нижнем классе был всего один объект базового класса, то есть чтобы не было неоднозначности. Я щас даже не представлю как это, но я вижу что у тебя в классах нету ни одной виртуальной функции, так что можешь спокойно просто делать наследование без 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
class C1
{
protected:
    int a;
public:
    C1():a(1){std::cout << "Konstructor C1\n";}
    ~C1(){std::cout << "Destructor C1\n";}
    virtual int Get();
};
class C2: virtual public C1
{
protected:
    int b;
public:
    C2():b(2){std::cout << "Konstructor C2\n";}
    ~C2(){std::cout << "Destructor C2\n";}
    virtual int Get();
};
class C3: virtual public C1
{
protected:
    int c;
public:
    C3():c(3){std::cout << "Konstructor C3\n";}
    ~C3(){std::cout << "Destructor C3\n";}
    virtual int Get();
};
class C4: public C2,public C3
{
protected:
    int d;
public:
    C4():d(4){std::cout << "Konstructor C4\n";}
    ~C4(){std::cout << "Destructor C4\n";};
    virtual int Get();
    
};
 
using namespace std;
int main()
{
    C1 * pointer;
    pointer = new C4();
    cout << pointer->Get();
    cout <<endl;
 
 
    return 0;
}
int C1::Get()
{
    return a;
}
int C2::Get()
{
    return b;
}
int C3::Get()
{
    return c;
}
int C4::Get()
{
    return d;
}
А еще поговорим о наследовании без virtual public, а просто public, что же у нас тогда происходит? Как я выше писал неоднозначность в самом нижнем классе должно быть два объекта самого верхнего базового класса в данном случае С1. Я честно сразу не понял почему неоднозначность, но щас догадался. Наверно потому, что С1 является также базовым классом и для C4, а там при наследовании без virtual хранится два объекта С1 и наверно механизм виртуальных функций не знает какой объект выбрать, чтобы вызвать функцию или C1::C2 или C1::C3, а если с virtual, то там всего один объект C1 оказывается и поэтому можно сделать виртуальный вызов. Просто других ответов я не вижу как еще это можно объяснить, да еще и в книге, вроде так как то написано.

Меня от еще мучает вопрос, а если построить ромб из 6 классов, в самом нижнем классе также будет один экземпляр базового класса? Просто лень тестить. По идее должен быть один. Если да тогда можно додумать, что виртуальное наследование применяется только для верхних классов. Ну в общем тестить нада, просто интересно. Если понял что я имею введу можешь протестить как оно будет. Ну или щас я попробую.
Psilon
Master of Orion
 Аватар для Psilon
5737 / 4685 / 619
Регистрация: 10.07.2011
Сообщений: 14,160
Записей в блоге: 5
Завершенные тесты: 4
16.05.2013, 00:21     Виртуальное наследование (указатель на базовый класс) #16
ninja2, а еще можно глянуть на вики уже разобранный пример
http://ru.wikipedia.org/wiki/%D0%A0%...BD%D0%B8%D0%B5
akk
 Аватар для akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
16.05.2013, 00:26  [ТС]     Виртуальное наследование (указатель на базовый класс) #17
ninja2, спасибо!, А можете прикинуть UML диаграмму на 6 ромбов, а то я не могу понять что вы имеете ввиду
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.05.2013, 00:32     Виртуальное наследование (указатель на базовый класс)
Еще ссылки по теме:

C++ Наследование классов С++ (не могу правильно унаследовать базовый класс)
C++ Простое наследование в с++. Базовый класс (AEROFLOT) и дочерний (REIS)
Наследование: базовый класс - массив, наследник - матрица C++

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

Или воспользуйтесь поиском по форуму:
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
16.05.2013, 00:32     Виртуальное наследование (указатель на базовый класс) #18
akk, Да от что я имел введу просто "вытянутый ром".

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
class C1
{
protected:
    int a;
public:
    C1():a(1){std::cout << "Konstructor C1\n";}
    ~C1(){std::cout << "Destructor C1\n";}
    virtual int Get();
};
class C2: virtual public C1
{
protected:
    int b;
public:
    C2():b(2){std::cout << "Konstructor C2\n";}
    ~C2(){std::cout << "Destructor C2\n";}
    virtual int Get();
};
class C3: virtual public C1
{
protected:
    int c;
public:
    C3():c(3){std::cout << "Konstructor C3\n";}
    ~C3(){std::cout << "Destructor C3\n";}
    virtual int Get();
};
class C4: public C2
{
protected:
    int d;
public:
    C4():d(4){std::cout << "Konstructor C4\n";}
    ~C4(){std::cout << "Destructor C4\n";};
    virtual int Get();
    
};
class C5: public C3
{
protected:
    int d;
public:
    C5():d(5){std::cout << "Konstructor C5\n";}
    ~C5(){std::cout << "Destructor C5\n";};
    virtual int Get(){return d;}
    
};
class C6: public C4,public C5
{
protected:
    int d;
public:
    C6():d(6){std::cout << "Konstructor C6\n";}
    ~C6(){std::cout << "Destructor C6\n";};
    virtual int Get(){return d;}
    
};
 
using namespace std;
int main()
{
    C1 * pointer;
    pointer = new C6();
    cout << pointer->Get();
    cout <<endl;
 
 
    return 0;
}
int C1::Get()
{
    return a;
}
int C2::Get()
{
    return b;
}
int C3::Get()
{
    return c;
}
int C4::Get()
{
    return d;
}
Просто самого давно мучал вопрос, а тестить было лень.
Если попробовать из верхушки убрать virtual, то в самом нижнем классе будет хранится два объекта С1 с каждой ветки и уже виртуальный вызов нельзя сделать.
Yandex
Объявления
16.05.2013, 00:32     Виртуальное наследование (указатель на базовый класс)
Ответ Создать тему
Опции темы

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