Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.doc
Скачиваний:
12
Добавлен:
24.09.2019
Размер:
187.39 Кб
Скачать

8) Закрытые конструк­торы (статический метод - "фабрика" объектов класса).

Закрытый конструктор — это особый конструктор экземпляров. Обычно он используется в классах, содержащих только статические элементы. Если в классе один или несколько закрытых конструкторов и ни одного открытого конструктора, то прочие классы (за исключением вложенных классов) не смогут создавать экземпляры этого класса.

class NLog

{// Private Constructor:

private NLog() { }

public static double e = Math.E; //2.71828...}

Закрытые конструкторы используются, чтобы не допустить создание экземпляров класса при отсутствии полей или методов экземпляра, например для класса Math, или когда осуществляется вызов метода для получения экземпляра класса. Если все методы в классе являются статическими, имеет смысл сделать статическим весь класс.

"фабрика" объектов класса

class A{ int a;

A(){a=0;} static A*create();

~A(){} static void destroy(*A);

public: int getA(){return a;}

int seta(int x){a=x;}

int main { A a; // в функции main нельзя вызвать конструктор А

Если конструкторы закрытые, то можно создать открытый метод класса.

A *p; p=A::create(); A::destroy(p);

9) Друзья класса. Закрытые конструкторы ("фабрика" объектов класса - внешняя функция - друг класса)

Для класса дружеств. м.б. объявлена внешняя функция, метод другого класса, или другой класс. Если ф. или метод объявлен другом класса, тогда они имеют доступ и к закрытой и открытой части класса.

("фабрика" объектов класса - внешняя функция - друг класса

class A{int a;

friend void f(); Если класс А друг В, то не значит что В друг А.

friend A* create(); Если А друг В, В друг С, А не друг С.

friend void destroy(A*);}

void f(){…}

int main(){f();

A *p; p=A::create(); A::destroy(p);}

10) Перегрузка операций. Пример: операция сложения. Когда операцию нельзя перегрузить как метод класса. Операция помеще­ния в поток.

В С++ в общем случае операцию можно перегрузить с помощью не статического метода класса, либо с помощью внешней функции.

Особенности перегрузки операций в С++:

- нельзя перегружать операции для стандартных типов, только для собственных классов.

- нельзя придумать собственный значок операции.

- для перегруженных операций нельзя изменять арность, приоритет и ассоциативность.

- нельзя перегружать след. операции :: (Разрешение области видимости), sizeof, ?: (Условный оператор сравнения), . (Выбор элемента), .* (Указатель на элемент).

- операции =, [], (), -> могут перегружаться только с помощью метода класса.

- для перегруженных операций нельзя задавать значения по умолчанию.

- перегруженные операции, кроме присваивания, наследуются.

рекомендуетcя перегружать как методы класса только те операторы, которым требуется изменить защищенные члены.

Перегрузка операция сложения

Class A{ int a;

public: A(int x=0): a(){}

int getA(){return 0;}

void setA(int x){a=x;}

A operator+(A a2){return A(a+a2.a);}

A operator+(int x){return A(a+x);}

int main(){ A a1(2), a2(4), a3;

a3=a1+a2; // a3=a1.operator+(a2);

a3=a1+10; // преобразование конструктором преобразования

return 0;}

Если перегр. операция сложения получает, не значение объекта, а ссылку на объект, тогда компилятору не нужно создавать новый объект, поэтому не вызывается конструктор и не происходит преобразование.

Операция помеще­ния в поток.

cout << a << endl

Class A{ int a;

friend ostream& operator<<(ostream& o, A a); }

Т.к. операция помещения в поток вв качестве своего первого аргумента использует обьект некоторого стандартного класса. Её нельзя переопределить как метод нашего класса. Можно только с помощью внешней ф-ии, обычно друж. функции.

ostream&.operator<<(ostream& o, A a){return o<<a;}

11) Пространства имен в Си. Пространства имен в C++. Вложенные пространства имен. Безымянные пространства имен. Псевдонимы для пространств имен, using директива и using-объявление.

Пространства имен – средства для избежания конфликта имен.

В СИ 4 пространства имен: (1) Тэги (2) Имена полей

(3)Имена переменных, функций, типов (4)Содержит метки.

Struct (1)Student { char (2)Student[20];}

(3)Student;

int m; goto m; (4)m:a=x;}

В С++ можно создавать собственные пространства имен.

namespace lib1{ namespace lib2{

void draw(){} } void draw(){} }

int main(){ lib1::draw(); lib2::draw();}

Псевдонимы для пространств имен,

namespace ATT=American_Telephone_And_Telegraph;

int main(){ ATT::f();}

using директива и using-объявление.

using namespace ATT; //делает напрямую видимыми из одного пространства имен в другом, в том, где размещена деректива using

Чтобы делать видимыми одно имя, нужно использовать using обьявление. using ATT::f;

Вложенные пространства имен

namespace A{ int x;

namespace B{ void f(){…} }

int main(){ A::B::f();} или {using A::B::f; f();}

Безымянные пространства имен - альтернатива static.

Все имена, описанные в безымянном пространстве, доступны в текущем файле и больше нигде, как если бы мы к каждому описанию приписали static.

12) Пакеты в Java

ava package (пакет Java) — механизм, позволяющий организовать Java классы в пространства имен 

Java пакеты могут содержаться в сжатом виде в JAR файлах. Обычно в пакеты объединяют классы одной и той же категории, либо предоставляющие сходную функциональность.

  • Каждый пакет предоставляет уникальное пространство имен для своего содержимого.

  • Допустимы вложенные пакеты.

Классы, определенные без явно заданных модификаторов доступа (publicprotectedprivate), видимы только внутри пакета.

Class

Package

Subclass

World

private

Y

 —

 —

(без)

Y

Y

 —

protected

Y

Y

Y

public

Y

Y

Y

Y

  • private — доступ только внутри класса (наиболее рекомендуемый)

  • (без модификатора) — только внутри пакета (по умолчанию)

  • protected — межпакетный доступ только для sub-class

  • public — межпакетный доступ (наименее рекомендуемый)

13 )Отношения между классами: агрегирование и композиция. Пример, класс Stack на основе чужого класса List.

Отношения агрегирования. Агрегирование возникает, если полями одного класса(агрегата) являются объекты других классов (частей агрегата). Частным случаем агрегирования явл. – композиция – возникает если при разрушении, части не могут существовать самостоятельно.

stack.h list.h

#include “list.h” class List{public: void add(int index, int elem);

class Stack{ List data; void dell(int index);

public: void push(int); int get(int index);

int pop(); void set(int index, int value);

int top(); int size();

bool isempty();}; bool isempty(); }

Stack.cpp

#include “list.h”

void Stack::push(int elem){data.add(0, elem);}

int Sack::pop(){int tmp=data.get(0); data.del(0); return tmp;}

int Sack::top(){ return data.get(0);}

bool Stack::isempty(){return data.isempty();}

14)Отношения между классами: наследование. (расширение)

Насле́дование — механизм объектно-ориентированного программирования  позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются новым классом.

Class Base{}; Class Derived : [вид наследования] Base{}

Выды наследования: private; public; protected

class B : public A {}; // public наследование, все методы и public переменные класса A видны и у B class C : protected A {};  // protected наследование, методы и переменные класса А доступны только классу А и его (класса C) наследникам сlass D : private A {};  // переменные и методы класса А никому не доступны, кроме А и D

15) Модификатор protected. protected эквивалентен private, и только для классов, производных от данного аналогичен public.

16) Виды наследования в C++. Пример, класс Stack на основе чужого класса List.

Насле́дование — механизм объектно-ориентированного программирования  позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются новым классом.

Class Base{}; Class Derived : [вид наследования] Base{}

Выды наследования: private; public; protected, virtual

class B : public A {}; // public наследование, все методы и public переменные класса A видны и у B class C : protected A {};  // protected наследование, методы и переменные класса А доступны только классу А и его (класса C) наследникам сlass D : private A {};  // переменные и методы класса А никому не доступны, кроме А и D виртуальное наследование применяется для разрешения конфликтов при множественном наследовании.

stack.h list.h

#include “list.h” class List{public: void add(int index, int elem);

class Stack: private List{ List data; void dell(int index);

public: using base::isampty; //конструкция восстановления ур-ня доступа

void push(int); int get(int index);

int pop(); void set(int index, int value);

int top(); int size();

bool isempty();}; bool isempty(); }

Stack.cpp

#include “list.h”

void Stack::push(int elem){data.add(0, elem);}

int Sack::pop(){int tmp=data.get(0); data.del(0); return tmp;}

int Sack::top(){ return data.get(0);}

bool Stack::isempty(){return data.isempty();}

Правильным отношение агрегирования, а не расширения, т.к. результир. класс обладает меньшими возможностями чем класс List.

17) Наследование в Java и С#.

C#

Пример наследования от одного класса и двух интерфейсов:

public class A { }

public interface I1 { }

public interface I2 { }

public class B : A, I1, I2 { }

Наследование от типизированных классов можно осуществлять, указав фиксированный тип, либо путем переноса переменной типа в наследуемый класс:

public class A<T>{ }

public class B : A<int>{ }

public class B2<T> : A<T> { }

Допустимо также наследование вложенных классов от классов, их содержащих:

class A { public class B : A { }}

Директива sealed в объявлении класса делает наследование от него невозможным.

В Java бывает только implements - реализация интерфейса interface A {} class B  implements A {} И собственно наследование  class A {} class C extends A {} В Java есть множественное наследование интерфейсов, но нет множественного наследования реализации.

18) Переопределение методов базового класса в производном классе

public class C1

{

public virtual void M1()

{ Console.WriteLine("C1.M1"); }

}

public class C2 : C1

{

public override void M1()

{ base.M1();

Console.WriteLine("C2.M1");}}

19) Полиморфизм.

Полиморфное поведение возможно только для родственных классов.

Полиморфное поведение – когда в первом случае вызывается f() Base класса, а во втором f() Derived класса. Virtual дает полиморфность.

class Base{ class Derived: public Base{

public : virtual void f(){}; } public: virtual void f(){}; }

int main(){ Base b; Derived d; Base *pb;

pb=&b; pb -> f(); // f() класса Base

pb=&d; pb ->f(); // f() класса Derived }

20) Виртуальные функции. Механизм реализации виртуальных функций.

Чтобы объявить функцию как виртуальную, необходимо добавить ключевое слово virutal перед именем возвращаемого типа:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]