Разделы презентаций


Классы и сокрытие данных Дружественные функции презентация, доклад

Содержание

В стандарте языка С++ нет никаких ограничений по использованию статических переменных внутри классов. Однако в реализации объявление статических переменных внутри классов приводит к ошибке на стадии линковки. Для предотвращения данного эффекта следует

Слайды и текст этой презентации

Слайд 1
Классы и объекты
Продолжаем разговор…

Классы и объектыПродолжаем разговор…

Слайд 2 В стандарте языка С++ нет никаких ограничений по использованию

статических переменных внутри классов.
Однако в реализации объявление статических переменных внутри

классов приводит к ошибке на стадии линковки.
Для предотвращения данного эффекта следует пользоваться следующей записью:
#include "iostream“
using namespace std;
class Cl {
static int n;
public:
Cl() { n++; cout << "Object #" << n << endl; }
};

int Cl::n=0;

void main()
{ Cl obj1, obj2, obj3; }

Статические переменные внутри класса


Результат



В стандарте языка С++ нет никаких ограничений по использованию статических переменных внутри классов.	Однако в реализации объявление

Слайд 3 При описании объектов при помощи классов программистом создается новый тип

данных, а переменная этого типа (экземпляр) и есть объект.
Если рассматривать

класс как новый тип данных, то в языке С++ можно создавать массивы объектов. Синтаксис – традиционен для языка С++.
Если задан произвольный класс Cl, то для создания одномерного массива объектов можно воспользоваться следующей записью:
class Cl { …};


void main()
{ Cl obj1[10]; }

Данная запись относится к случаю, когда в классе описан конструктор с аргументами по умолчанию.
Если в классе есть только конструкторы с аргументами и отсутствует конструктор по умолчанию, то в этом случае необходимо при описании массива явно указывать передаваемые параметры:

Массивы объектов

При описании объектов при помощи классов программистом создается новый тип данных, а переменная этого типа (экземпляр) и

Слайд 4#include "iostream"

using namespace std;
class Cl {
int n;
public:
Cl(int k)

{ n = k; }
void print () {cout

"Elem =" << n << endl; }
};

void main()
{
Cl obj1[4] = { Cl(1), Cl(2), Cl(3), Cl(4) };
obj1[3].print();
}

Массивы объектов - пример

Если конструктор имеет только один аргумент, то запись можно сократить:

Cl obj1[4] = {1, 2, 3, 4 };

Доступ к открытым членам класса при описании массивов объектов производится через явное указание элемента массива и оператора точка:

obj1[3].print ();

#include

Слайд 5void main()
{
Cl obj1[4] = { Cl(1), Cl(2), Cl(3), Cl(4)

};
Cl* ptr;
ptr = &obj1[3];
ptr->print();
}
Указатели и ссылки

на объекты

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

void main(){ Cl obj1[4] = { Cl(1), Cl(2), Cl(3), Cl(4) }; Cl* ptr; ptr = &obj1[3];

Слайд 6Cl* ptr;
ptr = new Cl;
ptr->print();
delete ptr;

Указатели

и захват динамической памяти
Для доступа к компонентам класса по указателю

используется оператор (->).
Если был объявлен указатель на класс, то при помощи данного указателя можно выделить динамическую память под объект:

Cl* ptr;
ptr = new Cl(1,2);
ptr->print();
delete ptr;

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

Память можно выделять и под массивы объектов, однако невозможно осуществлять динамическую инициализацию массивов объектов

При удалении объекта при помощи оператора delete происходит автоматический вызов деструктора.

Cl* ptr; ptr = new Cl;  ptr->print(); delete ptr;Указатели и захват динамической памяти	Для доступа к компонентам

Слайд 7Вспомним о неприятных случаях, рассмотренных на предыдущей лекции, когда деструктор

содержит освобождение памяти и приходится применять конструктор копирования. Чтобы обойти

такие ситуации можно использовать ссылки на объекты. Важно: при использовании ссылок не происходит создания копии объектов, а соответственно не происходит и вызова деструктора копии!

Ссылки на объекты

В С++ можно объявлять ссылки на объекты.

#include "iostream“
using namespace std;
class Cl {
public:
int n;
Cl(int k) { n = k; }
void print () {cout << "Elem =" << n << endl; }
};

void func (const Cl &ob)
{ ob.n++; //ERROR!!!
ob.print(); //ERROR!!!
}
void main() { Cl ob1; func(ob1); }

При использовании ссылок на объекты в качестве аргументов функции встречаются ситуации, при которых нежелательны какие-либо изменения открытых компонентов класса. Для этого при описании ссылки ставится спецификатор const, говорящий о том, что компоненты данного объекта изменить нельзя.

Вспомним о неприятных случаях, рассмотренных на предыдущей лекции, когда деструктор содержит освобождение памяти и приходится применять конструктор

Слайд 8 В памяти для каждого располагаемого объекта создается специальный уникальный указатель.

Этот указатель делается доступным путем использования ключевого слова this. Правила:
каждому

объявляемому объекту соответствует свой скрытый this-указатель;
this-указатель может быть использован только для нестатической функции;
this указывает на начало своего объекта в памяти;
this не надо дополнительно объявлять;
this передается как скрытый аргумент во все нестатические (не имеющие спецификатора static) компоненты-функции своего объекта;
указатель this – локальная переменная и не доступна за пределами объекта;
обращаться к скрытому указателю можно this или *this.

Указатель this

В памяти для каждого располагаемого объекта создается специальный уникальный указатель. Этот указатель делается доступным путем использования ключевого

Слайд 9#include "iostream"

using namespace std;
class Cl {
public:
int n;
Cl(int n)

{ this->n = n; }
void print () {cout

"Elem =" << n << endl; }
};

void main()
{
Cl ob1;
}

Указатель this - пример


Слайд 10#include "iostream"

using namespace std;
class Cl {
public:
int n;

Cl(int n) { this->n = n; }
void print

() {cout << "Elem =" << n << endl; }
};

void main()
{
Cl ob1;
}

Указатель this - пример

А где здесь ошибка?


Слайд 11#include "iostream"

using namespace std;
class Cl {
public:
int n;

Cl(int n) { this->n = n; }
void print

() {cout << "Elem =" << n << endl; }
};

void main()
{
Cl ob1 (2);
}

Указатель this - пример


Слайд 12#include "iostream“
using namespace std;

class cls {
int n;
public:

void print() const
// { cout

n << endl; n++; }
{ cout << "n= " << n << endl; }
};

void main()
{
cls obj;
obj.print();
}


Спецификатор const

Спецификатор const может быть использован при описании функции-члена класса. Функция-член, описанная таким образом не может изменять неявные параметры!
Неявные параметры можно представить как список параметров, доступных через указатель this.

error C2166: l-value specifies const object

#include

Слайд 13#include "iostream"

using namespace std;

class cls {
int n;
public:

static void Conv() { n = 0;}
};

void main()
{
cls obj;

obj.Conv();
}
// Так нельзя!!!

Статические функции

Функции-члена класса могут быть объявлены как статические. Для этого используется ключевое слово static перед объявлением функции. Такая функция не может обращаться к любому из членов, используя указатель this . Это значит, что с ее помощью можно вести работу только с полями, отмеченными как static.

#include "iostream"

using namespace std;

class cls {
static int n;
public:
static void Conv() { n = 0;}
};

int cls::n = 0;

void main()
{
cls obj;
obj.Conv();
}


// Так можно!

#include

Слайд 14Вложенные классы
Язык С++ допускает вложенные классы – внутри тела одного

класса содержится объявление других классов.
Вложенные классы, подобно вложенным блокам, имеют

внешнюю и внутреннюю спецификацию.
Правила для вложенных классов изменились, по сравнению с языком С, где допускались вложенные структуры, но имена внутренних структур были видны извне.

char c;

class cls {
char c;
class XXX {
char c;
void func(char Ch) { ::c = cls::c = c =Ch; }
};

В классе XXX функция func, используя с ссылается на переменную cls::XXX::c.
C использование оператора разрешения контекста доступны три переменные с именем с.

Вложенные классы	Язык С++ допускает вложенные классы – внутри тела одного класса содержится объявление других классов.	Вложенные классы, подобно

Слайд 15Вложенные классы еще
Внутри блоков могут создаваться полностью локальные классы.
Определения таких

классов недоступны вне содержащего их локального блока.
Классы, определенные внутри функции,

не могут содержать статических членов.
Важно! С++ дает возможность создавать вложенные функции члены с использованием вложенных классов. Это – ограниченная форма вложенности функций. Функции-члены должны определяться внутри локального класса и на них нельзя ссылаться извне.
Как и в языке С, обычные вложенные функции запрещены.

void func()
{
class local { . . . } x;

. . . // все что угодно
};

local y; // запрещено, так как класс описан в контексте функции func

Вложенные классы еще	Внутри блоков могут создаваться полностью локальные классы.	Определения таких классов недоступны вне содержащего их локального блока.	Классы,

Слайд 16Класс - class
Структура - structure
Объединение (смесь) - union
Другие способы

описания объектов
Применение структур для описания объекта используется для поддержки совместимости

языков C и C++. Единственное отличие структуры от класса в С++ - это принятый по умолчанию модификатор доступа public ( для классов – private).
Для того, чтобы сделать некоторые компоненты структуры закрытыми – нужно перед их описанием указать атрибут private.

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

union int_dbl{
int i;
double d;
} n ={0};
// член i
// инициализируется
// нулем

Класс - class Структура - structureОбъединение (смесь) - unionДругие способы описания объектов	Применение структур для описания объекта используется

Слайд 17
Объединение - пример
#include "iostream"

using namespace std;

union w {
unsigned int

n;
unsigned char B[2];
w(int n) { this->n = n;

}
void conv () {cout << (int)B[1] << "." << (int)B[0] << endl; }
};

void main()
{
w W(257);
W.conv();
}

Результат: 1.1


Слайд 18
Объединение – пример 2
#include "iostream"

using namespace std;
enum week {mon, tues,

weds, thurs, fri, sat, sun};
union weekD {
int n;

week w;
};

void main()
{
weekD W;
W.n = 6;
if ( W.w== sat || W.w == sun) cout << " Its the weekend! \n";
}
Объединение – пример 2#include

Слайд 19
Объединение - ограничения
Объединения не могут наследовать какие-либо объекты
Объединения не могут

использоваться в качестве определения базовых объектов для других
Компоненты объединений не

могут иметь атрибут static
Объединения не могут содержать операции создания объектов, которые используют конструкторы и деструкторы. Сами они могут иметь конструкторы и деструктор.
Анонимные объединения могут иметь только public члены-данные.
Глобальные анонимные объединения должны быть объявлены статическими
Объединение - ограниченияОбъединения не могут наследовать какие-либо объектыОбъединения не могут использоваться в качестве определения базовых объектов для

Слайд 20 Инкапсуляция – это механизм языка программирования, который позволяет объединять

данные и код, взаимодействующий с этими данными.
Инкапсуляция – это

способность скрывать внутренние детали при предоставлении открытого интерфейса к определяемому пользователем типу данных.
Сокрытие данных – важный компонент ООП. Он позволяет создавать легче отлаживаемый и сопровождаемый код, потому что ошибки и модификации локализованы в нем.
В языке С++ для обеспечения инкапсуляции используются объявления класса или структуры, в сочетании с ключевыми словами, определяющими модификатор доступа (private, protected и public).
Ограничения доступа могут быть установлены как на уровне целых классов, так и на уровне отдельных компонент классов.
По правилам хорошего тона члены-данные должны помещаться в private часть объявления класса, и доступ к ним должен осуществляться с использованием функций-членов класса. Такая дисциплина доступа гарантирует, что пользователь не сможет вмешаться или неправильно использовать реализованный АТД (абстрактный тип данных).

Инкапсуляция – сокрытие данных

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

Слайд 21 Каждая функция и элемент данных, описанные внутри класса, имеют атрибут

доступа:

public (открытый) – доступ к элементам класса может быть осуществлен

как из самого класса, так и извне класса
private (закрытый) – доступ к элементам класса может быть осуществлен только из функций самого класса.
protected (защищенный) – имеет смысл при наследовании классов и будет рассмотрен позже

Атрибут доступа

По умолчанию все элементы класса имеют атрибут private . Атрибут задается соответствующим ключевым словом и символом «:». Действие атрибута сохраняется до следующего атрибута или до закрывающей фигурной скобки в объявлении класса.

Для структур по умолчанию все элементы класса имеют атрибут public .

Каждая функция и элемент данных, описанные внутри класса, имеют атрибут доступа:	public (открытый) – доступ к элементам класса

Слайд 22class My_cl {
public:
void Set(int n);
. .

.
protected :
. . .
private:
. . .
};
// public –

виден и доступен всем
// protected – виден и доступен только из базового класса и из
// производных классов
// private – виден и доступен только из базового класса

Где либо в программе:
My_cl clMy;
clMy.Set(a);

Инкапсуляция – идея

class My_cl { public: void Set(int n);  . . .protected : . . .private: . .

Слайд 23class My_str {
public:
void Get(int n);
int Var1;

. . .
protected :
int Var2;
. . .
private:

int Var3;
. . .
};

Где либо в программе:
My_str::Get(a);

Инкапсуляция - пример

. . .
void My_str::Get(int a)
{
int V;
V = V1;
V = V2;
V = V3;
. . .
};

void main()
{
My_str Obj;
Obj.V1 = 1;
Obj.V2 = 1; // Ошибка
Obj.V3 = 1; // Ошибка
}

” cannot access protected member”

cannot access private member

class My_str { public: void Get(int n);  int Var1;  . . .protected : int Var2;

Слайд 24При написании программ часто встречается ситуация, при которой необходимо иметь

доступ к закрытым компонентам классов. При использовании обычных внешних функций

это невозможно – возникают ошибки компиляции. Для решения данной задачи в С++ применяются так называемые дружественные функции. Для этого используется спецификатор friend. Отмеченная им функция:
не является методом-функцией этого класса;
имеет доступ ко всем компонентам этого класса (даже private).
Прототипы таких функций задаются в теле описания класса. Само тело такой функции может быть описано где угодно – и в классе, и за его пределами.
Лучше производить определение дружественной функции за пределами класса, подчеркивая тем самым тот факт, что функция не является компонентом класса.

Дружественные функции – общие положения

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

Слайд 25#include

using namespace std;
class C {
int n;
public:
C(int

n) {this->n = n; }; // конструктор
void print()

{ cout << "n="<< endl; }
friend void inc(C&);
};

void inc (C& obj) { obj.n++; }

void main ()
{ C obj(4); obj.print(); inc(obj); obj.print(); }

Дружественная функция (пример)

#include using namespace std;class C {  int n;public: C(int n) {this->n = n; };  //

Слайд 26Для того, чтобы дружественная функция осуществляла доступ к компонентам класса

необходимо в качестве аргумента передавать либо указатель либо ссылку на

объект.
Объявлять прототип дружественной функции можно в любом месте описания класса.
Атрибуты доступа для дружественных функций не играют роли.
Так как дружественная функция не является компонентом класса ее нельзя вызвать с использованием имени объекта или указателя на него. Вызов осуществляется обычным способом.
В С++ одна функция не может быть компонентой двух различных классов. Иногда возникает необходимость организации доступа к локальным данным нескольких классов из одной функции. Это еще одна (если не главная!) причина для использования дружественных функций.

Дружественная функция – объявление и вызов

Для того, чтобы дружественная функция осуществляла доступ к компонентам класса необходимо в качестве аргумента передавать либо указатель

Слайд 27#include
class B; // ссылка вперед – некоторый

// аналог прототипа функции
class C {


int k;
public:
C(int n) { k = n; }; // конструктор
friend char* equal (const C&, const B&);
};

class B {
int k;
public:
B(int n) { k = n*n; }; // конструктор
friend char * equal (const C&, const B&);
};

Дружественная функция (пример 2)

char* equal (const C &o1, const B &o2)
{
if (o1.k==o2.k) return ("C.k=B.k");
return ("C.k<>B.k");
}

void main ()
{
C obj1(4);
B obj2(0);
cout << equal(obj1, obj2) << endl;
}

#include class B; // ссылка вперед – некоторый       // аналог прототипа

Слайд 28Спецификатор friend классов
Дружественные функции могут быть перегружены.
Любой метод одного класса

может быть дружественным по отношению к другому классу. В этом

случае для доступа к компонентам классов в качестве аргументов необходимо лишь передать ссылки или указатели на объекты, для которой функция является дружественной.
Предположим, что для предыдущего примера функция equal является методом класса С и дружественной по отношению к классу B.
Тогда описания этой функции будут выглядеть так:
В классе С:
char* equal (const B&);
В классе B:
friend char* C::equal (const B&);


Спецификатор friend классовДружественные функции могут быть перегружены.Любой метод одного класса может быть дружественным по отношению к другому

Слайд 29#include
class A {
int i;
public:
friend class B;

A( ) : i(1) { }; // конструктор
~A(

) { };
void f1_A(const B&);
};
class B {
int j;
public:
friend class A;
B( ) : j(2) { }; // конструктор
~B( ) { };
void f1_B(const A& a)
{ cout << a.i + j << endl; }
};

Спецификатор friend классов


void A::f1_A(const B& b)
{ cout << i <<" "<
void main ( )
{
A aa;
B bb;
aa.f1_A(bb);
bb.f1_B(aa);
}


Результат выполнения программы:
1 2
3

Дружественными могут быть не только функции, но и классы.

#include class A {  int i;public: friend class B; A( ) : i(1) { };

Слайд 30Основные свойства и правила использования спецификации friend.
friend-функции не

являются компонентами класса, но имеет доступ ко всем его компонентам;

friend-функции не имеют доступа к указателю this;
friend-функции не наследуются в производных классах;
отношение friend не является ни симметричным, ни транзитивным:
A друг B не значит, что B друг A!
Если A друг B, а B друг C, то это не значит, что A друг C!
друзьями класса можно определить перегруженные функции. Каждая перегруженная функция, используемая как friend для некоторого класса, должна быть явно объявлена в классе со спецификатором friend.

Спецификатор friend классов - свойства

Основные свойства и правила использования спецификации friend. friend-функции не являются компонентами класса, но имеет доступ ко всем

Слайд 31Тесты …
Вопрос: Что будет выведено на экран в результате выполнения

программы?

#include

int main(void)
{
int a=5;
a

std::cout << a;
return 0;
}

Варианты ответа:

30
5
программа не скомпилируется
0
40

Тесты …Вопрос: Что будет выведено на экран в результате выполнения программы? #include int main(void){  int a=5;

Слайд 32Тесты …
Вопрос: Что будет выведено на экран в результате выполнения

программы?

#include

int main(void)
{
int a=5;
a

std::cout << a;
return 0;
}

Варианты ответа:

30
5
программа не скомпилируется
0
40


Оператор << означает сдвиг влево (на 3 разряда в данном случае), что равносильно умножению числа на 2 в степени, равной количеству разрядов, на которое сдвигается число. Исходя из этого, 5*2*2*2=40

Тесты …Вопрос: Что будет выведено на экран в результате выполнения программы? #include int main(void){  int a=5;

Слайд 33Тесты …
Вопрос: Чем классы отличаются от структур?
Варианты ответа:

Наличием полей разных

типов
Наличием функции-членов (методов)
Наличием имени
Модификатором доступа к полям и

методам по умолчанию
Тесты …Вопрос: Чем классы отличаются от структур?	Варианты ответа:Наличием полей разных типов Наличием функции-членов (методов) Наличием имениМодификатором доступа

Слайд 34Тесты …
Вопрос: Чем классы отличаются от структур?
Структуры (как и классы)

могут иметь имя, поля и методы. Но для полей и

методов структур модификатор доступа по умолчанию – public.

Варианты ответа:

Наличием полей разных типов
Наличием функции-членов (методов)
Наличием имени
Модификатором доступа к полям и методам по умолчанию


Тесты …Вопрос: Чем классы отличаются от структур?Структуры (как и классы) могут иметь имя, поля и методы. Но

Слайд 35Тесты …
Вопрос: Корректен ли код с точки зрения выделения ресурсов?


#include
using namespace std;
class A {
private:
int x;
public:

A():x(10){}
};
A &foo()
{
return *(new A); //1
}
int main()
{
A &a=foo(); //2
delete &a; //3
return 0;
}

Варианты ответа:

- Код не корректен
- Ошибка в строке 3
- Ошибка в строке 1
- Ошибка в строке 2
- Код корректен

Тесты …Вопрос: Корректен ли код с точки зрения выделения ресурсов? #include using namespace std;class A {private:

Слайд 36Тесты …
Вопрос: Корректен ли код с точки зрения выделения ресурсов?


#include
using namespace std;
class A {
private:
int x;
public:

A():x(10){}
};
A &foo()
{
return *(new A); //1
}
int main()
{
A &a=foo(); //2
delete &a; //3
return 0;
}

Варианты ответа:

- Код не корректен
- Ошибка в строке 3
- Ошибка в строке 1
- Ошибка в строке 2
- Код корректен


В строке 1 разыменовывается указатель, чтобы вернуть ссылку на объект, в строке 2 возвращается объект, в строке 3 в оператор delete передается адрес высвобождаемой области.
Оператор delete освобождает память, выделенную в функции foo().

Тесты …Вопрос: Корректен ли код с точки зрения выделения ресурсов? #include using namespace std;class A {private:

Слайд 37Тесты …
Вопрос: Скомпилируется ли следующий код:

class cls
{
public:
cls()

{ }
~ cls() { }
void f(cls

* p){ delete p; }
};

void main()
{
cls* p = new cls;
p->f(p);
}
Тесты …Вопрос: Скомпилируется ли следующий код: class cls{public:  cls() { }  ~ cls() { }

Слайд 38Тесты …
Вопрос: Скомпилируется ли следующий код:

class cls
{
public:
cls()

{ }
~ cls() { }
void f(cls

* p){ delete p; }
};

void main()
{
cls* p = new cls;
p->f(p);
}

Ответ «да».
Не смотря на то, что объект уничтожает сам себя. Метод f нормально отработает и будет вызван деструктор.

Тесты …Вопрос: Скомпилируется ли следующий код: class cls{public:  cls() { }  ~ cls() { }

Слайд 39Тесты …
Вопрос: Что выведет следующая программа:
#include "iostream"
#include

void main()
{

std::cout

Ошибка компиляции (stdio только в стандартной библиотеке языка С)

Ошибка компиляции (несоответствие типов)

Тесты …Вопрос: Что выведет следующая программа: #include

Слайд 40Тесты …
Вопрос: Что выведет следующая программа:
#include "iostream"
#include

void main()
{

std::cout

Ошибка компиляции (stdio только в стандартной библиотеке языка С)

Ошибка компиляции (несоответствие типов)

должно быть выведено "boom!5", т.к. printf() возвращает int, равный количеству символов, выведенных в stdout.
std::cout по умолчанию синхронизирован с stdout, поэтому вначале в stdout попадет "boom!", а затем - "5».


Тесты …Вопрос: Что выведет следующая программа: #include

Слайд 41Тесты …
Вопрос: Какое утверждение о следующем коде верно:

int main(int

argc, char* argv[])
{
int a[3] = { 1, 2, 3

};
int b[2] = { 1, 2 };
a = b;
return 0;
}

Варианты ответа:

Все нормально

Ошибка времени выполнения

Ошибка компиляции

Тесты …Вопрос: Какое утверждение о следующем коде верно: int main(int argc, char* argv[]){ int a[3] = {

Слайд 42Тесты …
Вопрос: Какое утверждение о следующем коде верно:

int main(int

argc, char* argv[])
{
int a[3] = { 1, 2, 3

};
int b[2] = { 1, 2 };
a = b;
return 0;
}

Варианты ответа:

Все нормально

Ошибка времени выполнения

Ошибка компиляции


error C2440: '=' : cannot convert from 'int [2]' to 'int [3]'

Тесты …Вопрос: Какое утверждение о следующем коде верно: int main(int argc, char* argv[]){ int a[3] = {

Обратная связь

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

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика