Автор: Пользователь скрыл имя, 08 Ноября 2011 в 12:07, шпаргалка
Работа содержит ответы на вопросы по дисциплине "Программирование".
return;
}
strcpy(fak,FAK);
}
~grup()
{ cout << "деструктор класса grup " << endl;
delete fak;
}
virtual void see(void);
// объявление виртуальной
};
class stud : public grup // производный класс
{ char *fam; // фамилия
int oc[4]; // массив оценок
public:
stud(char *FAK,long GR,char *FAM,int OC[]): grup(FAK,GR)
{ if (!(fam=new char[20]))
{ cout<<"ошибка выделения памяти"<<endl;
return;
}
strcpy(fam,FAM);
for(int i=0;i<4;oc[i]=OC[i++]);
}
~stud()
{ cout << "деструктор класса stud " << endl;
delete fam;
}
void see(void);
};
void grup::see(void) // описание виртуальной функции
{ cout << fak << gr << endl;}
void stud::see(void) //
{ grup ::see(); // вызов функции базового класса
cout <<setw(10) << fam << " ";
for(int i=0; i<4; cout << oc[i++]<<’ ’);
cout << endl;
}
int main()
{ int OC[]={4,5,5,3};
grup gr1("факультет 1",123456), gr2("факультет 2",345678), *p;
stud st("факультет 2",150502,"Иванов",OC);
p=&gr1; // указатель на объект базового класса
p->see(); // вызов функции базового класса объекта gr1
(&gr2)->see(); // вызов функции базового класса объекта gr2
p=&st;
// указатель на объект
p->see(); // вызов функции производного класса объекта st
return 0;
}
35.Множественное наследование.
В языке С++ имеется возможность образовывать производный класс от
нескольких базовых классов. Общая форма множественного наследования имеет вид class имя_произв_класса : имя_базового_кл 1,…,имя_базового_кл N { содержимое класса };
Иерархическая структура, в которой производный класс наследует от не-
скольких базовых классов, называется множественным наследованием. В этом случае производный класс, имея собственные компоненты, имеет доступ к protected- и public-компонентам базовых классов.
Конструкторы базовых классов при создании объекта производного клас-
са вызываются в том порядке, в котором они указаны в списке при объявлении производного класса. При применении множественного наследования возможно возникновение нескольких конфликтных ситуаций. Первая − конфликт имен методов или атрибутов нескольких базовых классов:
class A
{public: void fun(){}
};
class B
{public: void fun(){}
};
class C : public A, public B
{ };
int main()
{ C *c=new C;
c->fun(); // error C::f' is ambiguous
return 0;
}
При таком вызове функции fun() компилятор не может определить, к ка-
кой из двух функций классов A и B выполняется обращение. Неоднозначность можно устранить, явно указав, какому из базовых классов принадлежит вызываемая функция: c->A:: fun(); или c->B::fun();
Вторая проблема возникает при многократном включении некоторого
базового класса:
#include <iostream>
using namespace std;
#include <string.h>
class A // базовый класс I уровня
{ char naz[20]; // название фирмы
public:
A(char *NAZ) {strcmp(naz,NAZ);}
~A() {cout << "деструктор класса А" << endl;}
void a_prnt() {cout << naz << endl;}
};
class B1 : public A // производный класс (1 Базовый II уровня)
{ protected:
long tn;
int nom;
public:
B1(char *NAZ,long TN,int NOM): A(NAZ),tn(TN),nom(NOM) {};
~B1() {cout << "деструктор класса В1" << endl;}
void b1_prnt()
{ A::a_prnt();
cout << " таб. N " << tn <<" подразделение = " << nom <<endl;
}
};
class B2 : public A // производный класс (2 Базовый II уровня)
{ protected:
double zp;
public:
B2(char *NAZ,double ZP): A(NAZ),zp(ZP) {};
~B2(){cout << "деструктор класса В2" << endl;}
void b2_prnt()
{ A::a_prnt();
cout << " зар/плата = " << zp << endl;
}
};
class C : public B1, public B2 // производный класс ( III уровня)
{ char *fam;
public:
C(char *FAM,char *NAZ,long TN,int NOM,double ZP) :
B1(NAZ,TN,NOM), B2(NAZ,ZP)
{ fam = new char[strlen(FAM)+1]
strcpy(fam,FAM);
};
~C() {cout << "деструктор класса С" << endl;}
void c_prnt()
{ B1::b1_prnt();
B2::b2_prnt();
cout << " фамилия " << fam<<endl;
}
};
int main()
{ C cc("Иванов","мастра",1234,2,
// cc.a_prnt(); ошибка 'C::a_prnt' is ambiguous
// pt->a_prnt();
cc.b1_prnt();
pt->b1_prnt();
cc.b2_prnt();
pt->b2_prnt();
cc.c_prnt();
pt->c_prnt();
return 0;
}
В приведенном примере производный класс С имеет по цепочке два оди-
наковых базовых класса А (A<-B1<-C и A<-B2<-C), для каждого базового класса А строится свой объект (рис. 3, 4). Таким образом, вызов функции
cc.a_prnt(); pt->a_prnt();некорректен, так как неизвестно, какую из двух функций (какого из двух классов А) требуется вызвать.
36.Множественное наследование и виртуальные базовые классы
Если базовый класс (в приведенном выше примере это класс А) является
виртуальным, то будет построен единственный объект этого класса.
#include <iostream.h>
using namespace std;
class A
{ int aa;
public:
A() {cout<<"Конструктор1 класса A"<<endl;}
A(int AA) : aa(AA) {cout<<"Конструктор2 класса A"<<endl;}
~A() {cout<<"Деструктор класса A"<<endl;}
};
class B : virtual public A
// производный класс (первый
{ char bb;
public:
B() {cout<<"Конструктор1 класса B"<<endl;}
B(int AA,char BB): A(AA), bb(BB)
{cout<<"Конструктор2 класса B"<<endl;}
~B() {cout<<"Деструктор класса B"<<endl;}
};
class C : virtual public A
// производный класс (второй
{ float cc;
public:
C() {cout<<"Конструктор1 класса C"<<endl;}
C(int AA,float CC) : A(AA), cc(CC)
{cout<<"Конструктор2 класса C"<<endl;}
~C() {cout<<"Деструктор класса C"<<endl;}
};
class D : public C,public B // производный класс (II уровня)
{ int dd;
public:
D() {cout<<"Конструктор 1 класса D"<<endl;}
D(int AA,char BB,float CC,int DD) :
A(AA), B(AA,BB), C(AA,CC), dd(DD)
{cout<<"Конструктор 2 класса D"<<endl;}
~D() {cout<<"Деструктор класса D"<<endl;}
};
void main()
{ D d(1,'a',2.3,4);
D dd;
}
Результат работы программы:
Конструктор 2 класса A (конструкторы для объекта d)
Конструктор 2 класса C
Конструктор 2 класса B
Конструктор 2 класса D
Конструктор 1 класса A (конструкторы для объекта dd)
Конструктор 1 класса C
Конструктор 1 класса B
Конструктор 1 класса D
Деструктор класса D (деструкторы для объекта d)
Деструктор класса B
Деструктор класса C
Деструктор класса A
Деструктор класса D (деструкторы для объекта d)
Деструктор класса B
Деструктор класса C
Деструктор класса A
Виртуальный базовый класс всегда инициализируется только один раз. В
примере при создании объектов d и dd конструктор класса А вызывается из конструктора класса D первым и только один раз, затем конструкторы классов B и C, в том порядке, в котором они описаны в строке наследования классов: class D : public B, public C . В одно и то же время класс может иметь виртуальный и невиртуальный базовые классы, например:
class A{ … };
class B1: virtual public A{ … };
class B2: virtual public A{ … };
class B3: public A{ … };
class C: public B1, public B2, public B3 { … };
В этом случае класс С имеет два подобъекта класса А, один наследуемый
через классы В1 и В2 (общий для этих классов) и второй через класс В3 .
37.Абстрактные классы .