Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
pEntity
74 / 93 / 22
Регистрация: 12.12.2012
Сообщений: 1,099
1

Вызов членов и объектов с наследника класса

13.12.2014, 14:07. Просмотров 319. Ответов 13
Метки нет (Все метки)

Есть базовый класс и два наследника:

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
class CBase
{
    public:
 
        int iNum;
        virtual void CBase_init( );
};
 
class CStart : public CBase
{
    public:
 
        int iStart;
        virtual void Start_init( );
};
 
class CEnd : public CBase
{
    public:
 
    int iEnd;
        
        virtual void End_init( );
};
C++
1
std::vector<CBase*> pVector;
C++
1
2
pVector.push_back( new CStart ( ) );
pVector.push_back( new CEnd ( ) );
Как мне вызвать iEndиз CEnd? У меня просто нет доступа к нему:

C++
1
pVector.at( 2 /* class CEnd */ )->iEnd;
iValue не доступен.

Есть доступ только ко всему, что есть в CBase.

А мне например нужно изменить iStart из CStart , потом его узнать в CEnd.

Или нужно их объявить в CBase и далее у каждого объекта будет свое значение, но если так, то например изменив значение iValue в CStart , у CEnd оно будет нулю ровно..
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.12.2014, 14:07
Ответы с готовыми решениями:

Вызов конструктора базового класса из класса-наследника
Можно ли вне списка инициализации вызвать конструктор базового класса ? ...

Вызов деструктора класса-наследника
Всем привет! есть базовый класс и класс-наследник class Base { public:...

Вызов виртуального метода класса наследника из вектора
#include &lt;iostream&gt; #include &lt;vector&gt; using namespace std; class A {...

Массив объектов класса. Печать строк-членов класса.
подскажите, как распечатать строки? #include &quot;myString.h&quot; #include...

Правда, что указатель класса-наследника не может указывать на объект класса-родителя?
Доброго времени суток! Пример кода ниже. Правда ли , что указатель...

13
DrOffset
8134 / 4716 / 1153
Регистрация: 30.01.2014
Сообщений: 7,688
13.12.2014, 14:36 2
pEntity, сначала свел все к базовому классу, а потом пытаешься получить частный случай. Определиться надо бы
Если уж используешь полиморфизм, то и изменять состояние класса нужно полиморфно, в виртуальных методах.

Цитата Сообщение от pEntity Посмотреть сообщение
А мне например нужно изменить iStart из CStart , потом его узнать в CEnd.
Это же разные объекты, как ты собрался изменять данные в одном объекте и получать их в другом?
Я пока что только могу тебе посоветовать продолжить читать теорию. Что-то ты здесь явно недопонял.

Цитата Сообщение от pEntity Посмотреть сообщение
то например изменив значение iValue в CStart , у CEnd оно будет нулю ровно..
Правильно, потому что это разные объекты. Они магическим образом друг с другом не свяжутся.
1
hoggy
Нарушитель
Эксперт С++
7083 / 3127 / 647
Регистрация: 15.11.2014
Сообщений: 7,180
Завершенные тесты: 1
13.12.2014, 14:42 3
Доступ к наследникам:

На практике, профессиональные программисты называют подобные поделия "говнокод":


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
#include <vector>
#include <iostream>
using namespace std;
 
 
class CBase
{
    public:
        int iNum;
        virtual void CBase_init(){}
};
 
class CStart : public CBase
{
    public:
    int iStart;
    virtual void Start_init(){}
};
 
class CEnd : public CBase
{
    public:
    int iEnd;
    virtual void End_init(){}
};
 
int main()
{
    std::cout << "Hello, world!\n";
    
    std::vector<CBase*> pVector;
    
    pVector.push_back( new CStart );
    pVector.push_back( new CEnd   );
    
    
    
    dynamic_cast<CEnd*>(pVector.at(1))->iEnd;
}
Добавлено через 1 минуту
Цитата Сообщение от pEntity Посмотреть сообщение
А мне например нужно изменить iStart из CStart , потом его узнать в CEnd.
Вот здесь поподробнее.

Вы сами понимаете, что написали? Вы понимаете, чего вы хотите?
1
pEntity
74 / 93 / 22
Регистрация: 12.12.2012
Сообщений: 1,099
13.12.2014, 14:56  [ТС] 4
Не понимаю)

Ну вот смотрите:

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
#include <vector>
#include <iostream>
 
using namespace std;
 
class CBase
{
    public:
        int iNum;
 
        virtual void init(){ iNum = 5;  }
};
 
class CStart : public CBase
{
    public:
 
    virtual void init(){ printf( "CStart %d\n", iNum ); }
};
 
class CEnd : public CBase
{
    public:
 
    virtual void init(){ printf( "CEnd %d\n", iNum ); }
};
 
int main()
{
    std::vector<CBase*> pVector;
   
    pVector.push_back( new CBase );
    pVector.push_back( new CStart );
    pVector.push_back( new CEnd );
    
    for( int i = 0; i < (int)pVector.size(); i++ )
    {
        pVector.at(i)->init();
    }   
    
    system("pause");
}
Изменил iNum в CBase, а как узнать его в CStart и CEnd?
0
hoggy
Нарушитель
Эксперт С++
7083 / 3127 / 647
Регистрация: 15.11.2014
Сообщений: 7,180
Завершенные тесты: 1
13.12.2014, 15:23 5
Цитата Сообщение от pEntity Посмотреть сообщение
Изменил iNum в CBase, а как узнать его в CStart и CEnd?
Так вы его и узнали. Вам в консольку напечатали значение этой переменной.

В ниже представленном коде член в базовом классе принимает значение 5.
А наследники печатают его в консоль:

http://rextester.com/ZBQVST23958

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
#include <vector>
#include <iostream>
 
using namespace std;
 
class CBase
{
    public:
        CBase(): iNum(5){}
    
        int iNum;
        virtual void init(){}
};
 
class CStart : public CBase
{
    public:
 
    virtual void init(){ printf( "CStart %d\n", iNum ); }
};
 
class CEnd : public CBase
{
    public:
 
    virtual void init(){ printf( "CEnd %d\n", iNum ); }
};
 
int main()
{
    std::vector<CBase*> pVector;
   
    pVector.push_back( new CBase );
    pVector.push_back( new CStart );
    pVector.push_back( new CEnd );
    
    for( int i = 0; i < (int)pVector.size(); i++ )
        pVector.at(i)->init();
}
0
pEntity
74 / 93 / 22
Регистрация: 12.12.2012
Сообщений: 1,099
13.12.2014, 15:33  [ТС] 6
Но вы изменили то в конструкторе. А мне нужна функция.

Мне нужно так:

В классе "А" вызываю функцию класса "Б", в "Б" меняется значение переменной, после получаю значение этой переменной в классе "Е" или любом другом.

Как курировать одной переменной между всеми классами, чтоб легко менять значение её и получать в любом другом ?
0
hoggy
Нарушитель
Эксперт С++
7083 / 3127 / 647
Регистрация: 15.11.2014
Сообщений: 7,180
Завершенные тесты: 1
13.12.2014, 16:07 7
Вы хотите что то такое?

http://rextester.com/ZKW9093


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
#include <iostream>
 
 
struct B
{
    virtual ~B(){}
    
    void SetValue(const int v){  CommonData()=v; }
protected:
    
    //так организуется хранение и доступ к общим данным семейства классов
    static int& CommonData() { static int v=10; return v; }
    
    //"семейство классов" - это иерархия классов, образованная от одного общего предка
    //как правило именно этот общий предок реализует
    //хранение и доступ к общим для всего семейства данным.
    
};
 
 
struct A: B
{
    void Work() { SetValue(333); }
};
 
 
struct E: B
{
    void View()const { ::std::cout << CommonData() << ::std::endl; }
};
 
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    // изначально общие для всего семейства данные имеют значение 10
        
    
    
    A a;
    // но в результате махинация объекта класса А, общие данные изменяют значение на 333
    a.Work();  
    
 
    E e;
    // напечатает в консоль 333, что означает, 
    e.View(); 
    //что объекты класса E видят все изменения общих данных, которые осуществляют объекты класса A
        
}
1
pEntity
74 / 93 / 22
Регистрация: 12.12.2012
Сообщений: 1,099
13.12.2014, 16:49  [ТС] 8
Я уж и не знаю, в общем, почему у меня тут не работает Reset и как исправить?

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
#include <iostream>
 
class CFIRST
{
    public:
 
        int iNum;
 
        void Reset() { iNum = 0; }
        void Calculate( );
 
};
 
class CTWO
{
    public:
 
        void Start( );
};
 
void CTWO::Start( )
{
    CFIRST First;
 
    First.Calculate( );
}
 
void CFIRST::Calculate( )
{
    printf( "DEBUG Pre: %d\n", iNum );
 
    iNum++;
 
    printf( "DEBUG Post: %d\n", iNum );
}
 
int main()
{
    CFIRST First;
    CTWO Two;
 
    First.Reset( );
    Two.Start( );
 
    system("pause");
}
0
hoggy
Нарушитель
Эксперт С++
7083 / 3127 / 647
Регистрация: 15.11.2014
Сообщений: 7,180
Завершенные тесты: 1
13.12.2014, 17:50 9
Цитата Сообщение от pEntity Посмотреть сообщение
Я уж и не знаю, в общем, почему у меня тут не работает Reset и как исправить?
Рекомендую вам ясно осознать, что такое "статические члены класса", и чем они отличаются от "членов класса".

В сообщении выше я привел вам пример рабочего кода.
Особенное внимание обратите на строки:

Цитата Сообщение от hoggy Посмотреть сообщение
//так организуется хранение и доступ к общим данным семейства классов
static int& CommonData() { static int v=10; return v; }
Изучите, что такое "локальные статические переменные", и в чем принципиальное отличие от использования "статических членов класса".

http://rextester.com/BTT36470

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
#include <iostream>
 
class CFIRST
{
    public:
 
        static int iNum; //<--- статический член класса. Не рекомендую к использованию
 
        void Reset() { iNum = 0; }
        void Calculate( );
};
int CFIRST::iNum=33;
 
class CTWO
{
    public:
        void Start( );
};
 
void CTWO::Start( )
{
    CFIRST First;
    First.Calculate( );
}
 
void CFIRST::Calculate( )
{
    printf( "DEBUG Pre: %d\n", iNum );
    iNum++;
    printf( "DEBUG Post: %d\n", iNum );
}
 
int main()
{
    CFIRST First;
    CTWO Two;
 
    First.Reset( );
    Two.Start( );
 
}
1
pEntity
74 / 93 / 22
Регистрация: 12.12.2012
Сообщений: 1,099
13.12.2014, 18:18  [ТС] 10
Спасибо. А это что такое ? int CFIRST::iNum=33;

Ну в общем то и работает, как я хотел. Правда наверно не лучший способ :-(. Я покажу, что я хочу, может вы предложите лучший вариант?

Есть класс человека. Есть класс самой регистрации.

Я хотел регать чела, потом обнулять их кол-во и снова регать..

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
class Alexandr: public CBase
{
    public:
 
        int g_iAlex;
        void Register_Init();
        // Другие данные..
 
};
 
class DBInfo : public CBase
{
    public:
 
        int g_iLoaded;
        int register_player( const char* psName, ... );
 
};
 
void Alexandr::Register_Init()
{
    g_iAlex = DBInfo.register_player( "Alex", ... );
}
 
int DBInfo::register_player( const char* psName, ... )
{
        printf( "DEBUG: %d\n", g_iLoaded);
 
        if( g_iLoaded>= 5 )
                return -1;
               
        // Other code..
        
        g_iLoaded++;
       
        return g_iLoaded- 1;
}
И вот в мэйне я вызываю Alexandr::Register_Init(), а обнулить g_iLoaded ни как не выходило.

Поможете что-то лучшее посоветовать по переустройству кода ?
0
hoggy
Нарушитель
Эксперт С++
7083 / 3127 / 647
Регистрация: 15.11.2014
Сообщений: 7,180
Завершенные тесты: 1
13.12.2014, 18:27 11
Цитата Сообщение от pEntity Посмотреть сообщение
А это что такое ? int CFIRST::iNum=33;
С обычными членами класса все понятно: есть экземпляр класса. И значения его полей находятся в самом объекте: в куске памяти, которая была выделена под этот экземпляр.

Но как быть со статическими? Статическое поле существует вне экземпляров класса.
Оно является собственностью всего класса, а не отдельного какого то экземпляра.

Так где же по факту живет статическая переменная? Где она инициализируется?

Запись:
C++
1
int CFIRST::iNum=33;
Сообщает компилятору, в каком именно месте по факту будет жить переменная, и какое у неё должно быть стартовое значение.
0
Шенец Николай
10 / 10 / 5
Регистрация: 10.12.2014
Сообщений: 60
13.12.2014, 18:41 12
И вот в мэйне я вызываю Alexandr::Register_Init(), а обнулить g_iLoaded ни как не выходило.
Может вам просто не хватает конструктора класса DBInfo? Там и надо инициализировать все члены класса.

И вообще, hoggy прав, сначала разберитесь вообще с устройством классов, статическими и нестатическими членами класса, наследованием и полиморфизмом. Пока у вас не наблюдается признаков понимания и знания этих основ...
0
pEntity
74 / 93 / 22
Регистрация: 12.12.2012
Сообщений: 1,099
13.12.2014, 18:44  [ТС] 13
Шенец Николай, если конструктор там создать, да, она иницализируется нормально, я не могу её обнулить в процессе работы программы. Как мне её обнулить для DBInfo.
0
hoggy
Нарушитель
Эксперт С++
7083 / 3127 / 647
Регистрация: 15.11.2014
Сообщений: 7,180
Завершенные тесты: 1
13.12.2014, 18:54 14
Цитата Сообщение от pEntity Посмотреть сообщение
Есть класс человека. Есть класс самой регистрации.
Я хотел регать чела, потом обнулять их кол-во и снова регать..
http://rextester.com/EFCK83428

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
#include <string>
#include <iostream>
#include <set>
using namespace std;
 
typedef ::std::string
    Str;
 
struct Humman
{
    Humman(const Str& name)
        :mName(name)
    {}
    
    const Str& GetName()const 
      { return mName; }
    
private:    
    Str mName;
};
 
struct Registration
{
    typedef ::std::set<const Humman*>
        Bank;
    
    static void Reg(const Humman& h) 
    {
        cout<<"registration: '"<< h.GetName()<<"'\n";
        GetBank().insert(&h);
    }
    
    static void Reset()
    {
        cout<<"registration: clear\n";
        GetBank().clear();
    }
    
    static size_t Users()
    {
        cout << "registration: number of registrations: "
             << GetBank().size()<<'\n';
        
        return GetBank().size();
    }
    
private:
    static Bank& GetBank() 
        { static Bank b; return b; }
};
 
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    Humman vasya("Vasya Pupkin");
    Humman voloda("Volodya Pupkin");
    
    Registration::Reg(vasya);
    Registration::Reg(voloda);
    
    Registration::Users();
    
    Registration::Reset();
    
    Registration::Users();
   
}
по поводу механизма регистрации, могу продемонстрировать вам пример фабрики, которая умеет создавать объекты классов по символьному имени класса.

Принцип использования фабрики вот такой:

C++
1
2
3
4
5
6
7
//регистрируем класс Worker под именем "Worker"
Factory::Add<Worker>("Worker");
 
...
 
//просим фабрику создать объект класса Worker
auto& obj = Factory::Build("Worker");
Устройство фабрики очень простое,
но для его понимания необходимы базовые знания шаблонов с++
1
13.12.2014, 18:54
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.12.2014, 18:54

Вызов метода наследника
Доброго времени суток. Имеется 2 класса: class Text{ public: Text* txt;...

Вывод из класса наследника
У меня получается вывод из главного класса, а когда вывожу через функцию из...

Конструктор класса наследника
Я не могу понять свою ошибку к примеру если пишу так все нормально class...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

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