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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.92
GRANDEATH
39 / 39 / 1
Регистрация: 13.09.2009
Сообщений: 108
#1

Базовый класс и производный... - C++

28.09.2010, 17:16. Просмотров 1864. Ответов 8

Есть class A. У него есть функция protected foo();
Есть класс наследник B (class B: public A).
В классе-наследнике B есть функция g(), обращающаяся к foo() базового класса A;

Есть объект класса A:
A objA;

Каким образом можно вызвать функцию g(), для объекта objA???
По сути вопрос в следующим - как через объект базового класса вызвать функцию производного класса для работы с объектом базового класса?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.09.2010, 17:16
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Базовый класс и производный... (C++):

Есть производный класс и базовый; при чём производный использует только ЧАСТЬ ресурсов базового, правильно ли это? - C++
Ну то есть базовый класс A, с полями, допустим, a, b, c, d. И я проектирую производный класс B и я железно знаю, что он будет использовать...

Создать базовый класс - Array и производный класс - Money для работы денежной суммы - C++
ПОМОГИТЕ, ПОЖАЛУЙСТА, С ЗАДАЧЕЙ Создать базовый класс - Array и производный класс - Money для работы денежной суммы

Создать базовый класс Car (машина) и производный класс Lorry (грузовик): ООП ошибки - C++
Создать базовый класс Car (машина), характеризуемый торговой маркой (строка), числом цилиндров, мощностью. Определить методы переназначения...

Создать базовый класс Triad и производный класс vector3D - C++
Помогите пожалуйста с заданием. Часть кода(vector3D) сделал, вроде работает Нужно помочь с классом Triad. Вот полное задание: ...

Наследование: базовый класс Квадрат, производный класс Пирамида - C++
Помогите, пожалуйста!:cry: Добавлено через 6 минут Создать класс КВАДРАТ, член класса- длинна стороны. Предусмотреть в классе методы...

Указатели в базовом классе на базовый класс и производный класс - C++
Пишу контейнер "Бинарное дерево поиска" для частотного словаря. С самим контейнером особо вопросов нету. Вопрос по поводу элементов в...

8
obuhanoe
23 / 21 / 2
Регистрация: 25.08.2010
Сообщений: 93
28.09.2010, 17:45 #2
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
#include <iostream>
 
using namespace std;
 
class A
{
  public:
           A(){};
           ~A(){};
           virtual void g() = 0;
  protected:
           void foo(){cout<<"Hi";}
 
 
};
 
 
class B : public A
{
  public:
          B(){};
          ~B(){};
 
          virtual void g() {foo();};
 
};
 
 
int main()
{
 
   B objb;
   objb.g();
 
 
    return 0;
}
может вот так?
1
GRANDEATH
39 / 39 / 1
Регистрация: 13.09.2009
Сообщений: 108
28.09.2010, 17:54  [ТС] #3
Это вызов из объкта класса B функции класса B.

А как вызвать из
C++
1
2
 A objb;
   objb.g(); //?????
Добавлено через 1 минуту
Мы не можем вызвать foo напрямую.

Добавлено через 18 секунд
Зато можем вызвать g()
0
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
28.09.2010, 18:03 #4
Если я вас правильно понял:

C++
1
2
3
4
5
6
7
8
9
10
11
class A
{
   protected:
      void foo() { cout << "foo() called\n";  };
} objA;
 
class B : public class A
{
   public:
      void g(){ cout << "g() called\n\t" };
};
При таких условиях задачи я не вижу её решения: objA не принадлежит классу B и никогда вообще о нём не слышал.

Однако, вариант есть такой:

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 A
{
   protected:
      void foo() 
      { 
          cout << "foo() called\n";  
      };
 
   public:
      virtual void g() //обратите внимание на ключевое слово virtual
      {
          cout << "original g() called\n"; 
      };
} objA;
 
class B : public A
{
   public:
      virtual void g() //обратите внимание на ключевое слово virtual
      {
           cout << "g() called\n\t";
           foo(); 
      };
} objB;
 
int main( int argc, char ** argv )
{
   objA.g();                     //Вызовется g() из объекта типа A, как и должно быть
 
   A * ptrA = (A*)(&objB); //берём адрес objB, приводим его к типу указателя на A и
                                    //записываем в ptrA
 
   ptrA->g();                   //вызываем g() из объекта типа B, хотя указатель думает,
                                    //что указывает на объект типа A (см. виртуальные функции)
 
   return 0;
}
Что почитать:
Виртуальные функции, Таблица виртуальных методов

Ну и всё в этом роде.

Другого варианта пока не приходит в голову.

Удачи.
1
GRANDEATH
39 / 39 / 1
Регистрация: 13.09.2009
Сообщений: 108
28.09.2010, 18:51  [ТС] #5
Спасибо огромное. Код пашет, вот только этот способ обхода тоже не идет....
abstarry.h
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*------------------------------------------------------------------------*/
/*                                                                        */
/*  ABSTARRY.H                                                            */
/*                                                                        */
/*  Copyright Borland International 1991, 1992                            */
/*  All Rights Reserved                                                   */
/*                                                                        */
/*------------------------------------------------------------------------*/
 
#if !defined( __ABSTARRY_H )
#define __ABSTARRY_H
 
#if defined( TEMPLATES )
 
    #if !defined( __COLLECT_H )
    #include <Collect.h>
    #endif  // __COLLECT_H
 
    #if !defined( __MEM_H )
    #include <Mem.h>
    #endif  // __MEM_H
 
    #pragma option -Vo-
    #if defined( __BCOPT__ ) && !defined( _ALLOW_po )
    #pragma option -po-
    #endif
 
    _CLASSDEF(ostream)
    _CLASSDEF(ContainerIterator)
    _CLASSDEF(AbstractArray)
    _CLASSDEF(ArrayIterator)
 
    class _CLASSTYPE AbstractArray:  public Collection
    {
 
    public:
 
        friend class ArrayIterator;
 
        virtual Object _FAR & operator []( int loc ) = 0;
 
        virtual int lowerBound() const = 0;
        virtual int upperBound() const = 0;
        virtual sizeType arraySize() const = 0;
 
        virtual void detach( int loc, DeleteType dt = NoDelete ) = 0;
        virtual void detach( Object _FAR &, DeleteType dt = NoDelete ) = 0;
        void destroy( int i )
            {
            detach( i, Delete );
            }
 
        int isEqual( const Object _FAR & ) const;
        void printContentsOn( ostream _FAR & ) const;
 
    };
 
#else   // TEMPLATES
 
    #if !defined( __COLLECT_H )
    #include <Collect.h>
    #endif  // __COLLECT_H
 
    #if !defined( __MEM_H )
    #include <Mem.h>
    #endif  // __MEM_H
 
    #if !defined( __CHECKS_H )
    #include <Checks.h>
    #endif  // __CHECKS_H
 
    #pragma option -Vo-
    #if defined( __BCOPT__ ) && !defined( _ALLOW_po )
    #pragma option -po-
    #endif
 
    _CLASSDEF(ostream)
    _CLASSDEF(ContainerIterator)
    _CLASSDEF(AbstractArray)
    _CLASSDEF(ArrayIterator)
 
    class _CLASSTYPE AbstractArray:  public Collection
    {
 
    public:
 
        AbstractArray( int, int = 0, sizeType = 0 );
        virtual ~AbstractArray();
 
        Object _FAR & operator []( int ) const;
 
        int lowerBound() const
            {
            return lowerbound;
            }
 
        int upperBound() const
            {
            return upperbound;
            }
 
        sizeType arraySize() const;
 
        virtual void detach( Object _FAR &, DeleteType = NoDelete );
        virtual void detach( int, DeleteType = NoDelete );
        void destroy( int i ) { detach( i, DefDelete ); }
        virtual void flush( DeleteType = DefDelete );
 
        virtual int isEqual( const Object _FAR & ) const;
        virtual void printContentsOn( ostream _FAR & ) const;
        //void printContentsOn( ostream _FAR & ) const;
 
        virtual ContainerIterator _FAR & initIterator() const;
 
    protected:
 
        Object _FAR & objectAt( int i ) const
            {
            return *theArray[ zeroBase(i) ];
            }
 
        Object _FAR *ptrAt( int i ) const
            {
            return theArray[ zeroBase(i) ];
            }
 
        int find( const Object _FAR & );
 
        void reallocate( sizeType );
 
        void setData( int, Object _FAR * );
 
        void insertEntry( int );
        void removeEntry( int );
        void squeezeEntry( int );
 
        sizeType delta;
        int lowerbound;
        int upperbound;
        int lastElementIndex;
 
    private:
 
        Object _FAR * _FAR *theArray;
 
        int zeroBase( int loc ) const
            {
            PRECONDITION( loc >= lowerbound && loc <= upperbound );
            return loc - lowerbound;
            }
 
        int boundBase( unsigned loc ) const
            {
            PRECONDITION( loc == UINT_MAX || loc <= upperbound - lowerbound );
            return loc == UINT_MAX ? INT_MAX : loc + lowerbound;
            }
 
        friend class ArrayIterator;
 
    };
 
    inline Object _FAR & AbstractArray::operator [] ( int atIndex ) const
    {
        return objectAt( atIndex );
    }
 
    inline sizeType AbstractArray::arraySize() const
    {
        return sizeType( upperbound - lowerbound + 1 );
    }
 
    class _CLASSTYPE ArrayIterator : public ContainerIterator
    {
 
    public:
 
        ArrayIterator( const AbstractArray _FAR & );
        virtual ~ArrayIterator();
 
        virtual operator int();
        virtual Object _FAR & current();
        virtual Object _FAR & operator ++( int );
        virtual Object _FAR & operator ++();
        virtual void restart();
 
    private:
 
        int currentIndex;
        const AbstractArray _FAR & beingIterated;
 
        void scan();
 
    };
 
#endif  // TEMPLATES
 
#if defined( __BCOPT__ ) && !defined( _ALLOW_po )
#pragma option -po.
#endif
#pragma option -Vo.
 
#endif  // __ABSTARRY_H
array.h
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
87
88
89
90
91
92
93
94
95
96
/*------------------------------------------------------------------------*/
/*                                                                        */
/*  ARRAY.H                                                               */
/*                                                                        */
/*  Copyright Borland International 1991, 1992                            */
/*  All Rights Reserved                                                   */
/*                                                                        */
/*------------------------------------------------------------------------*/
 
#if !defined( __ARRAY_H )
#define __ARRAY_H
 
#if defined( TEMPLATES )
 
    #if !defined( __ARRAYS_H )
    #include <Arrays.h>
    #endif  // __ARRAYS_H
 
    #pragma option -Vo-
    #if defined( __BCOPT__ ) && !defined( _ALLOW_po )
    #pragma option -po-
    #endif
 
    #define Array   BI_TCArrayAsVector
    #define PArray  PBI_TCArrayAsVector
    #define RArray  RBI_TCArrayAsVector
    #define RPArray RPBI_TCArrayAsVector
    #define PCArray PCBI_TCArrayAsVector
    #define RCArray RCBI_TCArrayAsVector
 
    _CLASSDEF( BI_TCArrayAsVector )
 
    #define ArrayIterator   BI_TCArrayAsVectorIterator
    #define PArrayIterator  PBI_TCArrayAsVectorIterator
    #define RArrayIterator  RBI_TCArrayAsVectorIterator
    #define RPArrayIterator RPBI_TCArrayAsVectorIterator
    #define PCArrayIterator PCBI_TCArrayAsVectorIterator
    #define RCArrayIterator RCBI_TCArrayAsVectorIterator
 
    _CLASSDEF( BI_TCArrayAsVectorIterator )
 
#else   // TEMPLATES
 
    #if !defined( __CLSTYPES_H )
    #include <ClsTypes.h>
    #endif  // __CLSTYPES_H
 
    #if !defined( __OBJECT_H )
    #include <Object.h>
    #endif  // __OBJECT_H
 
    #if !defined( __ABSTARRY_H )
    #include <AbstArry.h>
    #endif  // __ABSTARRY_H
 
    #pragma option -Vo-
    #if defined( __BCOPT__ ) && !defined( _ALLOW_po )
    #pragma option -po-
    #endif
 
    _CLASSDEF(Array)
 
    class _CLASSTYPE Array : public AbstractArray
 
    {
 
    public:
 
        Array( int upper, int lower = 0, sizeType aDelta = 0 ) :
            AbstractArray( upper, lower, aDelta )
            {
            }
 
        virtual void add( Object _FAR & );
        void addAt( Object _FAR &, int );
 
        virtual classType isA() const
            {
            return arrayClass;
            }
 
        virtual char _FAR *nameOf() const
            {
            return "Array";
            }
 
    };
 
#endif  // TEMPLATES
 
#if defined( __BCOPT__ ) && !defined( _ALLOW_po )
#pragma option -po.
#endif
#pragma option -Vo.
 
#endif  // __ARRAY_H
MyArray
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//#include <absarray.h>
#include <array.h>
 
 
_CLASSDEF(Array)
 
class _CLASSTYPE MyArray : public Array
{
     public:
      MyArray( int upper, int lower = 0, sizeType aDelta = 0 ) :
        Array( upper, lower, aDelta )
            {
        }
     virtual void removeEntry(int x)
     {
        removeEntry(x);
        //removeEntry
     }
};
То есть наследование Abstarry->Array->MyArray
Есть функция void removeEntry( int ); Она описана как protected.

Есть объект класса array. Из него надо вызвать функцию removeEntry, путем нового порожденного класса....

Добавлено через 1 минуту
Это реально запутано, но как есть(((
Проще класс A и класс B =))))

Добавлено через 1 минуту
Суть в том, что не могу я добавить функцию в public классу Abstarray, как сделали Вы в случае с g()...
У меня она в abstarray protected и называется removeEntry( int )(((((

Добавлено через 3 минуты
Не подумайте, что я псих(((( И что я кайфую от такого кода
это задание такое....
0
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
28.09.2010, 19:27 #6
Подождите, давайте сначала всё рассавим на свои места.

Как я понял, у вас есть 3 класса: Abstarray => Array => MyArray.
В MyArray реализована функция removeEntry, которой нет в Array.
Есть объект Array arrayObject. Вам нужно вызвать arrayObject.removeEntry();

Если я вас правильно понял, то это просто дурдом получается, другого слова не подберёшь. Суть наследования - в том, чтобы выделить общие свойства нескольких классов в один базовый класс. То есть если и для объектов MyArray, и для объектов Array должна быть доступна функция removeEntry, её нужно перенести либо в Array, либо в Abstarray.

Теоретически можно попробовать создать указатель на MyArray, присвоить ему адрес arrayObj и из него вызвать removeEntry, но ничего хорошего от такой техники не ждите. Если компилятор вообще вам такое простит.

Понимаете, допустим есть два класса:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class CExampleBase
{
public:
   int baseN;
   void print(){ cout << baseN; };
};
 
class CExample
{
public:
   int anotherN;
   void printBoth(){ print(); cout << "; " << anotherN; };
};
Технически при создании объекта класса выделяется память только под данные этого объекта, то есть, в случае с CExampleBase - под int CExampleBase::baseN. При вызове функции из класса компилятор скрыто от вас выполняет так называемый thiscall, то есть предаёт функции указатель на объект, с которым ей нужно работать:

C++
1
2
3
4
5
6
7
8
//этот код
CExampleBase obj;
obj.print();
 
//технически выглядит так:
struct TExampleBase{ int baseN; } obj;
print( &obj ); //вызов глобальной функции с передачей адреса банальной структуры,
                  //с которой ей нужно работать
При наследовании выглядит так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
//этот код
CExample obj;
obj.printBoth();
 
//технически выглядит так:
struct TExample
{ 
   int baseN; 
   int anotherN; //при наследовании данные просто выстраиваются
                      //друг за другом, в порядке наследования
} obj;
 
printBoth( &obj );
Теперь представьте себе:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
struct TExampleBase
{ 
   int baseN; 
   //int anotherN; // этой переменной тут нет, она появится только в TExample
} obj;
 
printBoth( (TExample*)(&obj) ); // вызываем функцию из TExample
//которая реализована так:
void printBoth( TExample * object )
{
   cout << object.baseN; //тут всё нормально, в нашем TExampleBase obj есть baseN
   cout << "; " << object.anotherN; // ERROR: попытка обратиться к данным, которых нет в структуре TExampleBase
}
То есть подобные дурилки ни к чему хорошему не приводят. Вы рискуете вылести за пределы структуры и хорошо, если не за пределы виртуального адресного пространства программы, то есть вызвать ошибку сегментации памяти. Видели когда-нибудь сообщение вроде "Error: read of address 0x000000"? Вот вы что-то подобное сделаете. Так что перечитывайте задание, скорее всего, либо оно некорректно поставлено, либо вы его некорректно восприняли.

Удачи.
1
GRANDEATH
39 / 39 / 1
Регистрация: 13.09.2009
Сообщений: 108
28.09.2010, 19:42  [ТС] #7
[quote=talis;990153]Как я понял, у вас есть 3 класса: Abstarray => Array => MyArray.[/quote
Да, верно
В MyArray реализована функция removeEntry, которой нет в Array.
Она не перегружна, но наследуется.


Вот кусок из задания...
10. Выполнить удаление одного элемента массива и снова его распечатать. На основе (показать два способа):
10.1. Нового порожденного от Array класса, в котором делается доступным метод removeEntry из класса AbstractArray. Там он защищен – protected;
Быть может я неправильно понял....Меня ставит в ступор "На основе нового порожденного от Array класса"
Цитата Сообщение от talis Посмотреть сообщение
и для объектов Array должна быть доступна функция removeEntry, её нужно перенести либо в Array, либо в Abstarray.
- Я полностью согласен!

Добавлено через 3 минуты
Цитата Сообщение от talis Посмотреть сообщение
class CExample { public: int anotherN; void printBoth(){ print(); cout << "; " << anotherN; }; };
А почему этот кусок кода должен работать? Быть может стоит написать
C++
1
2
3
4
5
6
class CExample: public CExampleBase
{
public:
   int anotherN;
   void printBoth(){ print(); cout << "; " << anotherN; };
};
???
0
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
28.09.2010, 20:02 #8
Цитата Сообщение от GRANDEATH
А почему этот кусок кода должен работать? Быть может стоит написать
Да, вы правы. Опечатка.

Цитата Сообщение от GRANDEATH
В MyArray реализована функция removeEntry, которой нет в Array. Она не перегружна, но наследуется.
Не перегружена - значит не переписана, наследуется - значит она содержится в базовом классе. А в вашей интерпретации она как раз таки не наследуется, а определяется в дочернем классе (MyArray).

Цитата Сообщение от GRANDEATH
10.1. Нового порожденного от Array класса, в котором делается доступным метод removeEntry из класса AbstractArray. Там он защищен – protected;
Как я понял, в классе AbstractArray есть protected void removeEntry(), вызов которого нужно сделать public в MyArray. Тогда:

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
class CExampleBase
{
    protected:
       void printstr ( char * whatToPrint ) // ваш removeEntry в AbstractArray
       {
           cout << "CExampleBase: " << whatToPrint << endl;
       };
};
 
class CExample : public CExampleBase
{
    public:
      void printstr( char * whatToPrint ) // ваш removeEntry в MyArray
      {
          CExampleBase :: printstr( whatToPrint ); // вызываете removeEntry из пространства имён AbstractArray
      };
};
 
int main( int, char** )
{
    CExample obj;
 
    obj.printstr( "Hello, world!" );
 
    return 0;
}
Тогда всё верно. Не поленитесь, скомпилируйте. Станет яснее.

Удачи.
1
GRANDEATH
39 / 39 / 1
Регистрация: 13.09.2009
Сообщений: 108
28.09.2010, 21:11  [ТС] #9
Спасибо большое. =)
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.09.2010, 21:11
Привет! Вот еще темы с ответами:

Создать базовый класс Тройка_чисел (Triad) и производный класс Time с полями часы, минуты и секунды - C++
Наследование. Виртуальныефункции.Полиморфизм. 1. Цельзадания: 1) Создание консольного приложения, состоящего и - Базовый класс:...

Базовый класс Liquid и производный класс Alcohol - C++
Создать класс Liquid, имеющий поля названия и плотности. Определить методы переназначения и плотности. Создать производный класс Alcohol,...

Базовый класс Complex и производный класс Vector - C++
Создайте базовый класс Complex (комплексное число) для реализации комплексных чисел в алгебраической форме и основных операций с ними:...

Базовый класс Student и производный класс Aspirant - C++
Задача была такова: Создайте класс Student, который будет содержать информацию о студенте. С помощью механизма наследования,...


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

Или воспользуйтесь поиском по форуму:
9
Yandex
Объявления
28.09.2010, 21:11
Ответ Создать тему
Опции темы

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