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

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

Войти
Регистрация
Восстановить пароль
 
 
akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
#1

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

15.05.2013, 23:27. Просмотров 1136. Ответов 17
Метки нет (Все метки)

У меня ромбическая иерархия классов, при попытке вызвать метод производного класса ошибка, что я не так делаю?
Вот исходный код
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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2013, 23:27     Виртуальное наследование (указатель на базовый класс)
Посмотрите здесь:
Наследование: базовый класс Квадрат, производный класс Пирамида C++
Указатель на базовый класс C++
C++ Указатель на базовый класс и на производный
C++ Абстрактный базовый класс и множественное наследование
Иерархия классов и указатель на базовый класс C++
C++ Указатель на базовый класс и дружественные функции
Наследование: базовый класс - массив, наследник - матрица C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
stima
457 / 306 / 24
Регистрация: 22.03.2011
Сообщений: 995
Завершенные тесты: 2
15.05.2013, 23:32     Виртуальное наследование (указатель на базовый класс) #2
Используете множественное наследование, хотя не знаете что такое обычное наследование. (Это ответ)
DU
1482 / 1058 / 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
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
15.05.2013, 23:42  [ТС]     Виртуальное наследование (указатель на базовый класс) #4
Все равно если заменить 29 строку на class C4: public C2, public C3
не работает.
DU, а как сделать чтобы можно было так вызывать метод
stima
457 / 306 / 24
Регистрация: 22.03.2011
Сообщений: 995
Завершенные тесты: 2
15.05.2013, 23:46     Виртуальное наследование (указатель на базовый класс) #5
Прочитайте что такое наследование.
akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
15.05.2013, 23:49  [ТС]     Виртуальное наследование (указатель на базовый класс) #6
stima, да я читал про обыкновенное наследование, а тут множественное, хочу разобраться в этом, можете подсказать?
Olivеr
412 / 408 / 13
Регистрация: 06.10.2011
Сообщений: 831
15.05.2013, 23:53     Виртуальное наследование (указатель на базовый класс) #7
Где множественное? Я не вижу у Вас классов которые имеют более одного родителя.
Кстати, в классе С1 надо сделать деструктор виртуальным, а то деструктор производного класса не вызывается.
stima
457 / 306 / 24
Регистрация: 22.03.2011
Сообщений: 995
Завершенные тесты: 2
15.05.2013, 23:55     Виртуальное наследование (указатель на базовый класс) #8
Цитата Сообщение от akk Посмотреть сообщение
stima, да я читал про обыкновенное наследование, а тут множественное, хочу разобраться в этом, можете подсказать?
Читали?) Напишите то что Вы хотите для 2 классов.
akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
16.05.2013, 00:01  [ТС]     Виртуальное наследование (указатель на базовый класс) #9
Цитата Сообщение от stima Посмотреть сообщение
Напишите то что Вы хотите для 2 классов.
я хочу чтобы созданный указатель базового класса с1 и инициализированного через с4, можно было вызывать все методы, которые есть сейчас в классах
Olivеr, даже если добавить virtual ~C1() все равно не работает
stima
457 / 306 / 24
Регистрация: 22.03.2011
Сообщений: 995
Завершенные тесты: 2
16.05.2013, 00:03     Виртуальное наследование (указатель на базовый класс) #10
Напишите это кодом для 2 классов один наследуеться од другого
Psilon
Master of Orion
Эксперт .NET
5882 / 4779 / 633
Регистрация: 10.07.2011
Сообщений: 14,399
Записей в блоге: 5
Завершенные тесты: 4
16.05.2013, 00:04     Виртуальное наследование (указатель на базовый класс) #11
Да видно же, человек делает по методе даже не задумываясь о том, что делает.
stima
457 / 306 / 24
Регистрация: 22.03.2011
Сообщений: 995
Завершенные тесты: 2
16.05.2013, 00:06     Виртуальное наследование (указатель на базовый класс) #12
Так вот я и пытаюсь добиться что-бы человек прочитал внимательней)
akk
44 / 44 / 7
Регистрация: 28.01.2012
Сообщений: 341
16.05.2013, 00:08  [ТС]     Виртуальное наследование (указатель на базовый класс) #13
stima, все методы в С1 должны быть чисто виртуальными?
Psilon
Master of Orion
Эксперт .NET
5882 / 4779 / 633
Регистрация: 10.07.2011
Сообщений: 14,399
Записей в блоге: 5
Завершенные тесты: 4
16.05.2013, 00:10     Виртуальное наследование (указатель на базовый класс) #14
stima, Наивно

akk, подсказка: чтобы вызвать полиморфный метод, используя указатель базового класса на объект производного класса, всеравно необходимо, чтобы в базовом классе этот метод существовал. Вы написали
C++
1
2
C1 *c1 = new C4();
c1->Get4(); //ошибка. в классе C1 НЕТУ метода Get4, а компилятор _не знает_, что на самом деле это C4, он считает его C1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.05.2013, 00:18     Виртуальное наследование (указатель на базовый класс)
Еще ссылки по теме:
Множественное наследование (Разработайте базовый класс CLIENT) C++
C++ Простое наследование в с++. Базовый класс (AEROFLOT) и дочерний (REIS)
C++ Наследование классов С++ (не могу правильно унаследовать базовый класс)
C++ Передача в контейнер объекта через указатель на базовый класс
Создание объекта через указатель на базовый абстрактный класс C++

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

Или воспользуйтесь поиском по форуму:
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 классов, в самом нижнем классе также будет один экземпляр базового класса? Просто лень тестить. По идее должен быть один. Если да тогда можно додумать, что виртуальное наследование применяется только для верхних классов. Ну в общем тестить нада, просто интересно. Если понял что я имею введу можешь протестить как оно будет. Ну или щас я попробую.
Yandex
Объявления
16.05.2013, 00:18     Виртуальное наследование (указатель на базовый класс)
Ответ Создать тему
Опции темы

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