
- •Int main()
- •Int main()
- •Int main()
- •Int main()
- •Int main()
- •Int main()
- •Int main()
- •Int main ()
- •Int main()
- •Int main()
- •Int main()
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
- •Int main(){
Int main()
{
int (A:: *pAmf) ();
pAmf=&A:: getA;
A a;
a.setA(100); // a.a=100;
int x = (a.* pAmf) ();
A *pa;
pa=&a;
(
(*
pa).* pAmf) (); эквивалентны
(pa -> * pAmf)();
int A:: * pAmd;
pAmd=& A:: a;
a.* pAmd =-1;
pA -> * pAmd=-1;
Отношения между классами.
А |
А |
-a:int |
+getA():int |
|
B |
связь между А и В
-> однонаправленная связь
<-> двунаправленная связь
Отношений
между классами множество.
Отношение агрегирования.
Когда один класс образуется из отдельных частей объектов другого класса (других классов).
Частный
случай агрегирования – композиция.
Такое отношение возникает, если при
уничтожении агрегата составные части
не могут существовать сами по себе.
Чтобы
создать класс агрегат, нужно в качестве
его полей задать объекты других классов
частей агрегатов.
Пример:
class A {}; //часть агрегата
class B {}; // агрегат
A a;
…
};
class A {
int a;
public:
A(int x) : a(x) {}
int getA() {return a;}
void setA (int x) {a=x;}
};
class B
{
A x;
A y;
public:
B (int d=0) : x(d) {} //-> A(int) (y(0))
int getA()
{
return x.getA();
}
};
Int main ()
{
B b;
int res = b.getA ();
…
При создании объекта класса В выделается память под его поле х, которое является объектом другого класса А. То есть создаются два объекта класса А и класса В. Для инициализации поля х должен быть вызван конструктор класса А. По умолчанию вызывается конструктор без аргументов. В примере для класса А не задан такой конструктор. Поэтому мы не можем создать объект класса В.
В списке инициализации конструктора класса В (агрегата) можно указать конструктор класса А, который должен вызываться для инициализации поля х.
Инициализация происходит в порядке объявления полей, а не в порядке, заданном в конструкторе.
Пример:
Собственный класс стек на основе чужого класса лист.
List.h
В классе лист должен быть конструктор без аргументов
Все узлы списка пронумерованы, начиная с 0.
Класс List умеет работать с целыми значениями.
List |
поля не интересуют нас |
+del (int index) +get (int index) : int +isEmpty () : bool +size () : int |
Stack |
|
+push (int elem) +pop () : int +top () : int +isEmpty () : bool |
stack.h
#include “List.h”
class stack
{
List data;
public:
void push (int elem);
int pop ();
int top ();
bool isEmpty ();
};
stack.cpp
#include “Stack.h”
void stack :: push (int elem)
{
data.add (0, elem);
}
int stack:: pop()
{
if (data.isEmpty())
/*типичная ситуация, когда должно быть выброшено исключение*/
return -1001001;
int res=data.get(0);
data.del(0);
return res;
}
int stack:: top()
{
return data.get(0);
}
bool stack:: isEmpty()
{
return data.isEmpty();
}
Отношение расширения (наследования).
-
manual
-
human
platypus |
Если между классами возникает отношение расширения или наследования, тогда некоторые из этих классов называют базовыми, родительскими, суперклассами, классами предками, а другие называют дочерними, подклассами, классами наследниками.
Производные классы получают все возможные состояния и все модели поведения родительских классов.
Различают единичное и множественное наследование.
-
A
-
B
-
C
-
C
-
A
B |
У класса С два базовых класса. Диаграмма 1) задает единичное наследование, диаграмма 2) – множественное. На диаграмме 1) класс В прямой базовый класс для С, а класс А – косвенный базовый класс для С через В. На диаграмме 2) А и В прямые базовые классы для С.
Если у класса более одного прямого предка, тогда наследование множественное, а если примой предок один, тогда наследование единичное.
С++ поддерживает как единичное, так и множественное наследование для классов.
Java и C# поддерживают только единичное наследование для классов.
Наследование в С++.
Единичное:
class Base{};
class Derived : public Base{};
В С++ существуют 3 вида наследования: public, private, protected.
В Java и C# наследование только открытое.
В С++ по умолчанию используется private (для class).
Если класс создан struct, то по умолчанию public.
В С++ для наследования нельзя использовать union.
class Base
{
protected: int b;
public:
Base (int x) : b(x) {}
int getB() {return b;}
void setB (int x) {b=x;}
};
class Derived : public Base
{
int d;
public:
Derived (int a, int b) : d(b)
Base (a) {}
int getD() {return d;}
};