|
Какой рейтинг вас больше интересует?
|
Главная /
Каталог блоговCтраница блогера das/Записи в блоге |
|
das
Голосов: 0 Адрес блога: http://ci-plus-plus.blogspot.com/ Добавлен: 2012-09-27 19:20:56 блограйдером daslex |
|
C++ для начинающих Символьный массив
2012-05-14 12:15:00 (читать в оригинале) Начинал писать скорее "между делом", а получится может очень полезным материалом. Просто возникло желание в программе использовать два варианта ввода в символьный массив значений. Первый вариант с клавиатуры, второй вариант из переменной. И оба варианта ввода в одной программе в один массив.
Вообще когда вы объявляете переменную-массив типа char, то компилятор автоматически определяет нужную длину для работы с таким массивом. При этом всё что есть в массиве, всё это остается в памяти и хоть вы и не видите этого, но вся строка забита информационным мусором. Многие книги об этом пишут, но вместе с этим многие игнорируют показательный материал, который даст понять что творится в символьном массиве на самом деле.
Для быстрого восприятия материала необходимы знания
Цикл for в С++ для начинающих
Функции в C++ для начинающих
Передача параметров в функции в C++ для начинающих
void full_S(char *S, int size) //Передача самой строки и ее размера
{
cout<<"S = ";
for (int i=1; i<size; i++) cout<<S[i]; // cout выполняется в цикле
cout<<endl; //этот cout вне цикла и выполняется один раз
}
void main()
{
clrscr();
const maxL=256; //Размерность для массива
char S[maxL]; //Объявили массив типа char
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
getch();
}
=================================
В принципе маленький и простой код. Внутри функции main() объявляется массив типа char. Если попытаться вывести этот массив как строку (cout<<S<<endl) сразу после того как объявлен, компилятор сам определяет, что нужно выводить на экран (Произойдет вывод на экран пустой строки). Если же проверить всю строку посимвольно, то можно увидеть сюрпризы.
Для вывода реальной строки на экран была написана отдельная функция full_S., которая занимается посимвольным выводом реальных значений всей строки.
Таким образом любой может увидеть реальную ситуацию работы с символьным массивом. Хотя компилятор и выводит на экран чистую строку, на самом деле это всего-лишь иллюзорная чистота, и вся строка может быть набита информационным мусором. Очень часто это первая причина ошибок
У любого кто понял вышеизложенное, может возникнуть стандартный вопрос: "Как же избавиться от этого непорядка". Ответ очень прост. Использовать функцию очистки массива или соорудить велосипед и написать свою.
void full_S(char *S, int size) //Функция посимвольного вывода строки по реальной длине
{
cout<<"S = ";
for (int i=1; i<size; i++) cout<<S[i]; // cout выполняется в цикле
cout<<endl; //этот cout вне цикла и выполняется один раз
}
void main()
{
clrscr();
const maxL=256; //Размерность для массива
char S[maxL]; //Объявили массив типа char
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
memset(S,NULL,maxL); //Очистили строку от мусора
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
getch();
}
=================================
Посмотрев на функцию memset несложно понять какие параметры ей нужны.
memset(Массив, Нулевое значение, Размерность массива) При обработке символов в качестве нулевого значения можно использовать '\0', но так можно перепутать куда слэш наклонен. Можно написать memset(Массив,0,Размерность) Но мне просто удобно указывать NULL, поэтому я использовал этот NULL в коде
Теперь смело можно писать программу для ввода символьного массива с клавиатуры и переприсваивание в него значения изнутри программы.
void full_S(char *S, int size) //Передача самой строки и ее размера
{
cout<<"S = ";
for (int i=1; i<size; i++) cout<<S[i]; // cout выполняется в цикле
cout<<endl; //этот cout вне цикла и выполняется один раз
}
void main()
{
clrscr();
const maxL=256; //Размерность для массива
char S[maxL]; //Объявили массив типа char
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
memset(S,NULL,maxL); //Очистили строку от мусора
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
cout<<endl<<endl;
cin>>S; //Вводим значение с клавиатуры;
full_S(S,maxL); //Символьный массив не содержит мусора, выше была очистка
memset(S,NULL,maxL); //Перед переопределением значения строки очищаем её от всего
strcpy(S,"1"); //Присваиваем строке нужное значение
full_S(S,maxL); //Проверка показала, что массив не содержит мусора
getch();
}
=================================
Таким образом, нужно следить за тем чтобы в строке не было того чего не нужно. Чтобы символьный массив/строка обрабатывались лучше, то перед занесением туда информации очищайте данные такого массива от всякого информационного мусора. Написание лишних строчек кода очистки массива программу вам скорее всего не испортит, а вот избежать возможных ошибок должно помочь.
Ведь при выполнении любого цикла программист заботится, чтобы изначально счетчик цикла был в первоначальном положении, символьный массив требует точно такой же заботы.
Вообще когда вы объявляете переменную-массив типа char, то компилятор автоматически определяет нужную длину для работы с таким массивом. При этом всё что есть в массиве, всё это остается в памяти и хоть вы и не видите этого, но вся строка забита информационным мусором. Многие книги об этом пишут, но вместе с этим многие игнорируют показательный материал, который даст понять что творится в символьном массиве на самом деле.
Для быстрого восприятия материала необходимы знания
Цикл for в С++ для начинающих
Функции в C++ для начинающих
Передача параметров в функции в C++ для начинающих
Код C++ Проверка всей строки посимвольно после объявления
================================= #include <conio.h>
#include <iostream.h>
void full_S(char *S, int size) //Передача самой строки и ее размера
{
cout<<"S = ";
for (int i=1; i<size; i++) cout<<S[i]; // cout выполняется в цикле
cout<<endl; //этот cout вне цикла и выполняется один раз
}
void main()
{
clrscr();
const maxL=256; //Размерность для массива
char S[maxL]; //Объявили массив типа char
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
getch();
}
=================================
В принципе маленький и простой код. Внутри функции main() объявляется массив типа char. Если попытаться вывести этот массив как строку (cout<<S<<endl) сразу после того как объявлен, компилятор сам определяет, что нужно выводить на экран (Произойдет вывод на экран пустой строки). Если же проверить всю строку посимвольно, то можно увидеть сюрпризы.
Для вывода реальной строки на экран была написана отдельная функция full_S., которая занимается посимвольным выводом реальных значений всей строки.
Таким образом любой может увидеть реальную ситуацию работы с символьным массивом. Хотя компилятор и выводит на экран чистую строку, на самом деле это всего-лишь иллюзорная чистота, и вся строка может быть набита информационным мусором. Очень часто это первая причина ошибок
У любого кто понял вышеизложенное, может возникнуть стандартный вопрос: "Как же избавиться от этого непорядка". Ответ очень прост. Использовать функцию очистки массива или соорудить велосипед и написать свою.
Код C++ Очистка массива с помощью memset
================================= #include <conio.h>
#include <iostream.h>
void full_S(char *S, int size) //Функция посимвольного вывода строки по реальной длине
{
cout<<"S = ";
for (int i=1; i<size; i++) cout<<S[i]; // cout выполняется в цикле
cout<<endl; //этот cout вне цикла и выполняется один раз
}
void main()
{
clrscr();
const maxL=256; //Размерность для массива
char S[maxL]; //Объявили массив типа char
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
memset(S,NULL,maxL); //Очистили строку от мусора
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
getch();
}
=================================
Посмотрев на функцию memset несложно понять какие параметры ей нужны.
memset(Массив, Нулевое значение, Размерность массива) При обработке символов в качестве нулевого значения можно использовать '\0', но так можно перепутать куда слэш наклонен. Можно написать memset(Массив,0,Размерность) Но мне просто удобно указывать NULL, поэтому я использовал этот NULL в коде
Теперь смело можно писать программу для ввода символьного массива с клавиатуры и переприсваивание в него значения изнутри программы.
Код C++ Считать строку из клавиатуры и переприсвоить ей значение из строковой константы
================================= #include <conio.h>
#include <iostream.h>
#include <string.h>
#include <string.h>
void full_S(char *S, int size) //Передача самой строки и ее размера
{
cout<<"S = ";
for (int i=1; i<size; i++) cout<<S[i]; // cout выполняется в цикле
cout<<endl; //этот cout вне цикла и выполняется один раз
}
void main()
{
clrscr();
const maxL=256; //Размерность для массива
char S[maxL]; //Объявили массив типа char
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
memset(S,NULL,maxL); //Очистили строку от мусора
full_S(S,maxL); //Передача строки и её размера в функцию посимвольного вывода
cout<<endl<<endl;
cin>>S; //Вводим значение с клавиатуры;
full_S(S,maxL); //Символьный массив не содержит мусора, выше была очистка
memset(S,NULL,maxL); //Перед переопределением значения строки очищаем её от всего
strcpy(S,"1"); //Присваиваем строке нужное значение
full_S(S,maxL); //Проверка показала, что массив не содержит мусора
getch();
}
=================================
Таким образом, нужно следить за тем чтобы в строке не было того чего не нужно. Чтобы символьный массив/строка обрабатывались лучше, то перед занесением туда информации очищайте данные такого массива от всякого информационного мусора. Написание лишних строчек кода очистки массива программу вам скорее всего не испортит, а вот избежать возможных ошибок должно помочь.
Ведь при выполнении любого цикла программист заботится, чтобы изначально счетчик цикла был в первоначальном положении, символьный массив требует точно такой же заботы.
С++ для начинающих Передача символьного массива в функцию
2012-05-11 23:21:00 (читать в оригинале) Иногда возникает необходимость передать символьный массив в функцию для обработки. Но при незнании материала это приводит к разным попыткам реализации, чаще не работающим чем рабочим. Поэтому, думаю, этот материал нельзя пропускать
Код C++ Обычная передача символьного массива в функцию
==================
void get_array(char S[])
{
S[0]='9'; //изменили первый символ
cout<<S<<endl;
}
void main()
{
clrscr();
char S[maxL]=""; //Инициализируем строку для очистки от мусора
cin.getline(S,maxL); //Ввели символьный массив с клавиатуры
get_array(S); //Передали массив в функцию
getch();
return;
}
==================
Достаточно простой для восприятия код. Следует обратить внимание, что внутри функции первым является нулевой элемент. Просто компилятор воспринимает такую передачу как передачу в функцию обычного массива. В параметрах для функции не нужно указывать размер строки, достаточно прописать тип char, имя переменной-массива и пустые квадратные скобки. Передача массива в функцию теперь выполняется с очень простым указанием переменной (имени массива)
void get_array(char *S)
{
S[0]='9'; //изменили первый символ
}
void main()
{
clrscr();
char S[maxL]=""; //Инициализируем строку для очистки от мусора
cin.getline(S,maxL); //Ввели символьный массив с клавиатуры
get_array(S); //Передали массив в функцию
cout<<S<<endl;
getch();
return;
}
==================
void get_array(char (&S)[maxL])
{
S[0]='9'; //изменили первый символ
}
void main()
{
clrscr();
char S[maxL]=""; //Инициализируем строку для очистки от мусора;
cin.getline(S,maxL); //Ввели символьный массив с клавиатуры
get_array(S); //Передали массив в функцию
cout<<S<<endl;
getch();
return;
}
==================
Очень похоже на передачу по указателю. Будьте внимательны к тому как написано в скобках
Код C++ Обычная передача символьного массива в функцию
==================
#include <conio.h>
#include <iostream.h>
const maxL=256;void get_array(char S[])
{
S[0]='9'; //изменили первый символ
cout<<S<<endl;
}
void main()
{
clrscr();
char S[maxL]=""; //Инициализируем строку для очистки от мусора
cin.getline(S,maxL); //Ввели символьный массив с клавиатуры
get_array(S); //Передали массив в функцию
getch();
return;
}
==================
Достаточно простой для восприятия код. Следует обратить внимание, что внутри функции первым является нулевой элемент. Просто компилятор воспринимает такую передачу как передачу в функцию обычного массива. В параметрах для функции не нужно указывать размер строки, достаточно прописать тип char, имя переменной-массива и пустые квадратные скобки. Передача массива в функцию теперь выполняется с очень простым указанием переменной (имени массива)
Код C++ Передача символьного массива в функцию с помощью указателя
================== #include <conio.h>
#include <iostream.h>
const maxL=256;void get_array(char *S)
{
S[0]='9'; //изменили первый символ
}
void main()
{
clrscr();
char S[maxL]=""; //Инициализируем строку для очистки от мусора
cin.getline(S,maxL); //Ввели символьный массив с клавиатуры
get_array(S); //Передали массив в функцию
cout<<S<<endl;
getch();
return;
}
==================
Код C++ Передача символьного массива в функцию с помощью ссылки
================== #include <conio.h>
#include <iostream.h>
const maxL=256;void get_array(char (&S)[maxL])
{
S[0]='9'; //изменили первый символ
}
void main()
{
clrscr();
char S[maxL]=""; //Инициализируем строку для очистки от мусора;
cin.getline(S,maxL); //Ввели символьный массив с клавиатуры
get_array(S); //Передали массив в функцию
cout<<S<<endl;
getch();
return;
}
==================
Очень похоже на передачу по указателю. Будьте внимательны к тому как написано в скобках
C++ для начинающих private, public, protected как модификаторы для наследования
2012-05-10 00:11:00 (читать в оригинале) После изучения модификаторов доступа внутри класса и простого наследования нужно понять принципы модификаторов доступа при наследовании. Многим людям легко запутаться что где есть. Чтобы как-то рассредоточить эту кашу, проще сначала понять что это за модификаторы доступа такие C++ для начинающих private, public, protected, а потом перейти к изучению модификаторов доступа при наследовании.
Я обычно не делал картинок и насыщал этот блог исключительно текстом, но тут с картинкой проще объяснить

Описаны три класса. На основе класса A строится класс B. На основе построенного класса B строится класс C Под пальцем показано как компилятором воспринимается код. В классе-потомке создаются такие же поля как и в классе-родителе, но они соответствуют только тому классу, в котором созданы
При наследовании public в класс-потомок передаются все поля в таком виде в котором они записаны в родителе. private поле тоже туда передается, но как я писал в статье C++ для начинающих Знакомство с protected (модификатор доступа внутри класса) , передается, но наследник ничего с ней сделать не может
Код C++ public наследование:
======================
class A
{
private: int x;
public: int y;
protected: int z;
};
class B:public A
{
public:
void update()
{
public:
void update() //Открытая для программы функция
{
x=100; //хотя private унаследован, в потомке он только ест память. Будет ошибка
y=100; //y из класса B стало равным 100
z=100; //z из класса B стало равным 100
}
}
};
class C:public B //Класс С является классом-потомком на основе класса B
{
public:
void update() //Открытая для программы функция
{
x=100; //хотя private унаследован, в потомке он только ест память. Будет ошибка
y=100; //y из класса C стало равным 100
z=100; //z из класса C стало равным 100
}
};
======================
Таким образом, используя public наследование мы передаем потомкам всё что есть в основном классе в таком виде, как и записано в основном классе. Поулучаем клон основного класса. Разница в том что элементы основного класса к элементам своего клона отношения не имеют
Код C++ private Наследование
=======================
class A
{
private: int x;
public: int y;
protected: int z;
};
class B:private A
{
public:
void upate()
{
x=100; //хотя private унаследован, в потомке он только ест память. Будет ошибка
y=200; //y определился как объявленный в private внутри класса Bz=200; //z определился как объявленный в private внутри класса B
}
};
class C:public B //Пытаемся создать потомок созданного класса B
{
public:
void update()
{
x=300; //Нельзя обратиться к private элементу унаследованному от родителя
y=300; //Нельзя обратиться к private элементу унаследованному от родителя
z=300; //Нельзя обратиться к private элементу унаследованному от родителя
}
};
=======================
Таким образом, используя private наследование можно создать первого потомка от которого дальнейшее наследование будет бессмысленно. Если первый потомок получает возможность работы с некоторыми элементами, переданными по механизму наследования, то потомки первого потомка таких возможностей не получают. Кроме того, потомки первого потомка даже лишены возможности узнавать кто их первый родитель. Предполагается, что потомки класса B не должны даже знать о существовании класса A (либо потомков класса B вообще не должно быть). (примечание: Под первым потомком подразумевается потомок первого уровня. Таких потомков может быть сколько угодно)
Код C++ protected наследование
========================
class A
{
private: int x;
public: int y;
protected: int z;
};
class B:protected A
{
public:
void update()
{
x=999; //Нельзя обратиться к private элементу унаследованному от родителя
y=999; //y определился как объявленный в protected внутри класса B
z=999; //z определился как объявленный в protected внутри класса B
}
};
class C:public B
{
public:
void update()
{
x=777; //Нельзя обратиться к private элементу унаследованному от родителя
y=777; //y определился как объявленный в protected внутри класса C
z=777; //z определился как объявленный в protected внутри класса C
}
};
========================
Таким образом, используя protected наследование, программист предполагает, что внутри всех потомков и потомков потомков и потомков потомков потомков будут использоваться только такие элементы, передаваемые механизмом наследования, которые будут защищены от внешнего воздействия извне своих классов.
Функции в C++ для начинающих Несколько выражений на месте одного параметра
2012-05-09 17:25:00 (читать в оригинале)Есть в C++ такой момент когда начинающий может запутаться читая чужую функцию. Бывает в самой функции прописан один параметр, а в программе в функцию передается более чем один. Разумеется должен возникнуть вопрос: "Что за безобразие, почему так?"
Код C++ Несколько выражений на месте одного параметра
============================
int func(int &N) //Параметр переданный в N будет обработан напрямую
{
N=N/2; //Делим переданный параметр в функцию пополам
return N; //Возвращаем вычисленное значение
}
void main()
{
clrscr();
int value=100; //value будем передавать как параметр вовнутрь функции
func(value, value=value/2, value=value*3); //Такой синтаксис допускается компилятором
cout<<value<<endl; //Выводим value на экран
getch();
return;
}
============================
Не знаю кому и когда такое надо, но возможность такая есть. Думаю не корректно говорить, что каждый такой элемент внутри функции обрабатывается как параметр. Насколько вижу я глазами новичка: В функцию как и должен, передается только один параметр, который обрабатывается функцией. За этот параметр передается крайний левый элемент из скобок. (value, value=...). Если изучать код дальше, то видно, что функция работает со ссылкой на то, что туда передается, значит то что я туда передаю при окончании работы функции поменяет свое значение в главной программе. (тема Ссылки в C++ для начинающих Поверхностное знакомство )
После срабатывания функции, value поменял свое значение на то что рассчитала функция и дальше я коверкаю код таким вот способом, где внутри параметров вместо параметров выполняю обычное присваивание в этот value своего значения, причем переприсваиваю значение дважды. Это можно и нужно было сделать после описания функции, но было написано внутри.
Возможно читающий посетитель этого блога встретит подобное написание программы и уже будет подготовлен к тому как правильно прочитать этот нелепый код. Мой совет - так не делать.
Я пришел к тому что:
Код C++ Несколько выражений на месте одного параметра
============================
#include <conio.h>
#include <iostream.h>
int func(int &N) //Параметр переданный в N будет обработан напрямую
{
N=N/2; //Делим переданный параметр в функцию пополам
return N; //Возвращаем вычисленное значение
}
void main()
{
clrscr();
int value=100; //value будем передавать как параметр вовнутрь функции
func(value, value=value/2, value=value*3); //Такой синтаксис допускается компилятором
cout<<value<<endl; //Выводим value на экран
getch();
return;
}
============================
Не знаю кому и когда такое надо, но возможность такая есть. Думаю не корректно говорить, что каждый такой элемент внутри функции обрабатывается как параметр. Насколько вижу я глазами новичка: В функцию как и должен, передается только один параметр, который обрабатывается функцией. За этот параметр передается крайний левый элемент из скобок. (value, value=...). Если изучать код дальше, то видно, что функция работает со ссылкой на то, что туда передается, значит то что я туда передаю при окончании работы функции поменяет свое значение в главной программе. (тема Ссылки в C++ для начинающих Поверхностное знакомство )
После срабатывания функции, value поменял свое значение на то что рассчитала функция и дальше я коверкаю код таким вот способом, где внутри параметров вместо параметров выполняю обычное присваивание в этот value своего значения, причем переприсваиваю значение дважды. Это можно и нужно было сделать после описания функции, но было написано внутри.
Возможно читающий посетитель этого блога встретит подобное написание программы и уже будет подготовлен к тому как правильно прочитать этот нелепый код. Мой совет - так не делать.
Я пришел к тому что:
- Несмотря на то что выглядит, что функция принимает несколько параметров, принимает она только столько сколько ей сказано и эти параметры идут первыми внутри скобок
- Если функции сказано принять N параметров, а принимает она N+1 или больше, то то что входит за этот N параметрами как таковыми не являются
C++ для начинающих Дружественные функции Первое знакомство
2012-05-08 23:03:00 (читать в оригинале)Эта статья описывает Дружественные функции. Точнее поверхностное ознакомление с дружественной функцией внутри класса.
Я как обычно думал введу в поиск, найду информацию и сразу всё пойму по теме. Не тут-то было. Думаю многих начинающих может волновать вопрос, описываемый в статье.
Само определение дружественной функции можно найти где угодно:
Дружественная функция - это функция, которая не являясь частью класса имеет доступ ко всем элементам из дружественного себе класса.
Казалось бы легкое и понятное определение. Объявил функцию внутри класса, дописал перед ней модификатор friend и используй как обычную и независимую от класса функцию вне класса. Если вы заинтересованы в этой теме, то попробуйте применить такую теорию на практике. Думаю подавляющее большинство попробовавших столкнутся с проблемами.
В качестве обучающего примера я приведу Код C++, в котором происходит сравнение обычной функции класса с дружественной функцией. Сравнение идет только по тому как пишется код в одном случае и как в другом. Вместе с этим вы можете прекрасно видеть синтаксис написания дружественной функции для класса
class A
{
int x; //Приватный элемент из класса A
friend void get_x(int, A &); //Прототип дружественной функции для занесение в приватный x значения
public:
void get_x(int); //Прототип обычного метода для занесения значения в приватный x
void show(); //Прототип функции для отображения x из приватного поля
};
void get_x(int N, A &obj_A) //Функция не является частью класса, но работает словно является
{
obj_A.x=N; //в элемент x класса A передается принимаемый параметр N
}
void A::get_x(int N) //функция является частью класса A
{
x=N; //в приватный элемент x класса A заносится принимаемый в N параметр
}
void A::show() //Функция является частью класса A и играет роль посредника
{
cout<<x<<endl; //Отображаем приватный элемент x из класса A
}
void main()
{
clrscr();
int value=100; //value будет передаваться как параметр вовнутрь класса в приватный x
get_x(value, obj_A); //Работаем как с обычной функцией.
obj_A.show(); //Отображаем результаты
value=999; //Изменили значение в value
obj_A.get_x(value); //Работаем как с методом объекта
obj_A.show(); //Отображаем результаты
getch();
return;
}
=================================
Сразу можно обратить внимание, что прототип дружественной функции описан внутри поля private. На самом деле можно его описывать и в других полях, но так видно одно важное отличие от обычных методов класса. В программе два абсолютно одинаковых по смыслу метода и оба выполняют одну и ту же задачу. Один метод дружественный, второй метод обычный. Так вот обычный метод из поля private был бы недоступен и без посредника он бы не знал что от него хотят, а дружественному методу посредник не нужен. Об этом и говорит часть теории:
Дружественная функция - это функция, которая не являясь частью класса имеет доступ ко всем элементам из дружественного себе класса.
Нас интересует именно дружественная функция из класса. Смотрим на её прототип и видим, что туда передается два параметра. Первый параметр является некоторым значением, которое будет заноситься в элемент класса, второй параметр - это ссылка на экземпляр класса. Так вот устроен механизм, что чтобы работать с элементами класса, нужно как-то сообщать независимой функции с каким классом ей работать, поэтому передается и значение с каким ей работать и сам экземпляр класса, элементы которого обрабатывать.
Так как элемент x был объявлен внутри private, то для отображения этого x необходим посредник, в качестве посредника работает функция show() . Функция show() объявлена внутри класса и значит все поля класса ей доступны. Я надеюсь вы изучили, что такое поле private и дальнейшее описание будет лишним
Коротко говоря:
Внутри класса объявлены
После описания класса идет написание функций.
Первой написана функция, которая принимает некоторый параметр N и принимает экземпляр класса, записывает этот N в x вовнутрь принятого экземпляра класса. Функция не опирается на класс и описана как самостоятельно-независимая. Возможно это как раз благодаря ключевому слову friend перед прототипом этой самой функции внутри класса. Еще раз отмечу, что такую функцию возможно описать внутри поля private
Второй описывается функция, которая принимает только один параметр. При этом функция опирается на класс A и следовательно заносит принимаемый параметр вовнутрь того класса на который и опирается.
В общем обе функции выполняют одно и то же действие, разница в том, что одна функция выполняется как самостоятельная и независимая от класса, при этом еще и описана внутри private. При всех этих обстоятельствах это не мешает ей работать вне класса без посредников
Вторая же функция опирается на некоторый класс и не может работать с элементами из поля private без посредников
В общем я пришел к тому что
Осталось только то, что находится внутри главной функции. Собственно там не должно возникнуть вопросов. Разница вызовов видна невооруженным глазом.
В первом случае обычная функция принимает параметры и обрабатывает их
Во втором случае обрабатываем класс через соответствующий объект
При этом первый вариант работы то же самое, что и второй.
Я как обычно думал введу в поиск, найду информацию и сразу всё пойму по теме. Не тут-то было. Думаю многих начинающих может волновать вопрос, описываемый в статье.
Само определение дружественной функции можно найти где угодно:
Дружественная функция - это функция, которая не являясь частью класса имеет доступ ко всем элементам из дружественного себе класса.
Дружественная функция объявляется внутри класса с модификатором friend
Казалось бы легкое и понятное определение. Объявил функцию внутри класса, дописал перед ней модификатор friend и используй как обычную и независимую от класса функцию вне класса. Если вы заинтересованы в этой теме, то попробуйте применить такую теорию на практике. Думаю подавляющее большинство попробовавших столкнутся с проблемами.
В качестве обучающего примера я приведу Код C++, в котором происходит сравнение обычной функции класса с дружественной функцией. Сравнение идет только по тому как пишется код в одном случае и как в другом. Вместе с этим вы можете прекрасно видеть синтаксис написания дружественной функции для класса
Код C++ Дружественная функция и обычная функция Класса
================================= #include <conio.h>
#include <iostream.h>
class A
{
int x; //Приватный элемент из класса A
friend void get_x(int, A &); //Прототип дружественной функции для занесение в приватный x значения
public:
void get_x(int); //Прототип обычного метода для занесения значения в приватный x
void show(); //Прототип функции для отображения x из приватного поля
};
/*Прототипы функций определены внутри класса. Сами функции описаны вне*/
void get_x(int N, A &obj_A) //Функция не является частью класса, но работает словно является
{
obj_A.x=N; //в элемент x класса A передается принимаемый параметр N
}
void A::get_x(int N) //функция является частью класса A
{
x=N; //в приватный элемент x класса A заносится принимаемый в N параметр
}
void A::show() //Функция является частью класса A и играет роль посредника
{
cout<<x<<endl; //Отображаем приватный элемент x из класса A
}
void main()
{
clrscr();
int value=100; //value будет передаваться как параметр вовнутрь класса в приватный x
get_x(value, obj_A); //Работаем как с обычной функцией.
obj_A.show(); //Отображаем результаты
value=999; //Изменили значение в value
obj_A.get_x(value); //Работаем как с методом объекта
obj_A.show(); //Отображаем результаты
getch();
return;
}
=================================
Сразу можно обратить внимание, что прототип дружественной функции описан внутри поля private. На самом деле можно его описывать и в других полях, но так видно одно важное отличие от обычных методов класса. В программе два абсолютно одинаковых по смыслу метода и оба выполняют одну и ту же задачу. Один метод дружественный, второй метод обычный. Так вот обычный метод из поля private был бы недоступен и без посредника он бы не знал что от него хотят, а дружественному методу посредник не нужен. Об этом и говорит часть теории:
Дружественная функция - это функция, которая не являясь частью класса имеет доступ ко всем элементам из дружественного себе класса.
Нас интересует именно дружественная функция из класса. Смотрим на её прототип и видим, что туда передается два параметра. Первый параметр является некоторым значением, которое будет заноситься в элемент класса, второй параметр - это ссылка на экземпляр класса. Так вот устроен механизм, что чтобы работать с элементами класса, нужно как-то сообщать независимой функции с каким классом ей работать, поэтому передается и значение с каким ей работать и сам экземпляр класса, элементы которого обрабатывать.
Так как элемент x был объявлен внутри private, то для отображения этого x необходим посредник, в качестве посредника работает функция show() . Функция show() объявлена внутри класса и значит все поля класса ей доступны. Я надеюсь вы изучили, что такое поле private и дальнейшее описание будет лишним
Коротко говоря:
Внутри класса объявлены
- Приватный элемент x
- Дружественная функция ввода в x значения
- Обычная функция ввода в x значения
- Функция для отображения приватного элемента
После описания класса идет написание функций.
Первой написана функция, которая принимает некоторый параметр N и принимает экземпляр класса, записывает этот N в x вовнутрь принятого экземпляра класса. Функция не опирается на класс и описана как самостоятельно-независимая. Возможно это как раз благодаря ключевому слову friend перед прототипом этой самой функции внутри класса. Еще раз отмечу, что такую функцию возможно описать внутри поля private
Второй описывается функция, которая принимает только один параметр. При этом функция опирается на класс A и следовательно заносит принимаемый параметр вовнутрь того класса на который и опирается.
В общем обе функции выполняют одно и то же действие, разница в том, что одна функция выполняется как самостоятельная и независимая от класса, при этом еще и описана внутри private. При всех этих обстоятельствах это не мешает ей работать вне класса без посредников
Вторая же функция опирается на некоторый класс и не может работать с элементами из поля private без посредников
В общем я пришел к тому что
- Функция friend может быть объявлена даже внутри private и посредники ей не нужны
- Обычная функция класса требует поcрединков для работы с элементами из private
Осталось только то, что находится внутри главной функции. Собственно там не должно возникнуть вопросов. Разница вызовов видна невооруженным глазом.
В первом случае обычная функция принимает параметры и обрабатывает их
Во втором случае обрабатываем класс через соответствующий объект
При этом первый вариант работы то же самое, что и второй.
Категория «Обзоры»
Взлеты Топ 5
|
| ||
|
+248 |
328 |
Русский Фольклор |
|
+241 |
284 |
Любер |
|
+209 |
319 |
Литературное кафе "ИСКУССТВО" |
|
+208 |
246 |
Kroshka_Strekoza |
|
+194 |
215 |
x_lightcore_x |
Падения Топ 5
|
| ||
|
-1 |
40 |
RichLife.ru |
|
-1 |
63 |
Гламурная Я |
|
-2 |
39 |
Водоочистка, водоподготовка. Самые низкие цены в Сибири! |
|
-3 |
21 |
Sebastian_Valmont |
|
-3 |
51 |
Диахронические мысли |
Популярные за сутки
Загрузка...
BlogRider.ru не имеет отношения к публикуемым в записях блогов материалам. Все записи
взяты из открытых общедоступных источников и являются собственностью их авторов.
взяты из открытых общедоступных источников и являются собственностью их авторов.
