|
Какой рейтинг вас больше интересует?
|
Главная /
Каталог блоговCтраница блогера das/Записи в блоге |
|
das
Голосов: 0 Адрес блога: http://ci-plus-plus.blogspot.com/ Добавлен: 2012-09-27 19:20:56 блограйдером daslex |
|
C++ для начинающих private, public, protected
2012-05-07 15:38:00 (читать в оригинале)Написание статьи о protected привело к написанию этой. Расписывая тот материал, я понял их основную разницу и понял для какого из случаев предназначены модификаторы доступа private, public и protected.
private - Модификатор доступа, обозначает, что программист будет использовать соответствующие элементы только внутри своего собственного класса
public - Модификатор доступа, который обозначает, что программист будет использовать соответствующие элементы либо в других частях программы, либо в других классах.
protected - Модификатор доступа, который определяет, что программист собирается применить наследование. В наследуемых классах он собирается унаследовать такие элементы, которые должны срабатывать как элементы private, но в отличии от private они расплодятся по всем наследникам и каждый такой элемент будет соответствовать только своему классу
Сейчас я попробую описать тоже самое используя художественный стиль (может кому пригодится)
Класс-наследник имеет поля и функции-члены базового класса, но не имеет права обращаться к собственным (private) полям и функциям базового класса
Вот и выходит так, что у основного класса есть такая часть, которую от сердца ему не оторвать, все наследники о ней знают, но использовать это не могут, так как Родитель отказался передавать эту часть по наследству. Такая часть - это private
Да вот мучает совесть родителя, не может он оставить детей без наследства, решает передать часть того, что у него есть всем своим потомкам. Передается эта тайна о родителя к потомку, но скрыта она от всех посторонних и доступна исключительно и только детям своим . Такая часть - это protected
А чтобы не вспоминали родителя словом плохим, он передает еще часть наследства своим потомкам и эта часть наследства озвучивается публично. Так как передали ее публично, то эта часть может попасть не в руки потомков и использовать эту часть наследования может любой шарлатан. Такая часть - public
Иногда задают вопрос: Если мы наследуем класс, наследуются ли приватные поля (члены)
Внимательный читатель видел, что написано: Класс-наследник имеет поля и функции-члены базового класса
Значит и поле private передается наследнику, но доступа к этому полю внутри класса нету. Выступает такой элемент в качестве виртуального паразита. Ведь для него внутри объекта выделяется память, в которой он зависает и тащится от безделья.
Ответ - Да, но использовать элементы внутри наследника из этих полей нельзя
Вообще много людей говорит и пишет, что приватные поля не наследуются. Не слушайте их. Они категорически неправы. Очень легко показать, что единственный и верный ответ тот, который я уже написал. Демонстрирую кодом
Код C++ private поля наследуются
==========================
class A
{
int a,b,c; //По умолчанию private.
};
class B:public A //Применили наследование и на основе класса A создали класс B
{
};
class C //Независимый класс
{
};
A obj_A; //Экземпляр класса A
B obj_B; //Экземпляр класса B
C obj_C; //Экземпляр класса С
void main()
{
clrscr();
cout<<sizeof(obj_A)<<endl; //Вывели на экран размер объекта от класса A
cout<<sizeof(obj_B)<<endl; //Вывели на экран размер объекта от класса B
cout<<sizeof(obj_C)<<endl; //Вывели на экран размер объекта от класса C
getch();
return;
}
==========================
Теперь смотрим на код. С одной стороны классы B и C ничего не содержат. Если в класс B ничего не унаследовалось, то B = C = пустой класс. Следовательно размеры объектов от этих классов должны быть равны друг другу. И надо же такому случится, в классе A нет ничего кроме приватных элементов. Вот тут-то и возникает момент истинны.
(obj_A=obj_B или obj_B=obj_C?)
При выводе на экран размеров объектов прекрасно видно, что первые два объекта равны и размер их заметно больше размера третьего объекта. Догадались почему? Потому что эти приватные элементы паразитируют не только виртуально, но и пудрят мозги бедным студентам. Существует только один правильный ответ про наследование приватных элементов по заданному вопросу. Этот ответ - Да, наследуются, висят в памяти, кроме пожирания памяти не делают ничего и использовать их нельзя. Одним словом - Паразиты
private - Модификатор доступа, обозначает, что программист будет использовать соответствующие элементы только внутри своего собственного класса
public - Модификатор доступа, который обозначает, что программист будет использовать соответствующие элементы либо в других частях программы, либо в других классах.
protected - Модификатор доступа, который определяет, что программист собирается применить наследование. В наследуемых классах он собирается унаследовать такие элементы, которые должны срабатывать как элементы private, но в отличии от private они расплодятся по всем наследникам и каждый такой элемент будет соответствовать только своему классу
Сейчас я попробую описать тоже самое используя художественный стиль (может кому пригодится)
Класс-наследник имеет поля и функции-члены базового класса, но не имеет права обращаться к собственным (private) полям и функциям базового класса
Вот и выходит так, что у основного класса есть такая часть, которую от сердца ему не оторвать, все наследники о ней знают, но использовать это не могут, так как Родитель отказался передавать эту часть по наследству. Такая часть - это private
Да вот мучает совесть родителя, не может он оставить детей без наследства, решает передать часть того, что у него есть всем своим потомкам. Передается эта тайна о родителя к потомку, но скрыта она от всех посторонних и доступна исключительно и только детям своим . Такая часть - это protected
А чтобы не вспоминали родителя словом плохим, он передает еще часть наследства своим потомкам и эта часть наследства озвучивается публично. Так как передали ее публично, то эта часть может попасть не в руки потомков и использовать эту часть наследования может любой шарлатан. Такая часть - public
Иногда задают вопрос: Если мы наследуем класс, наследуются ли приватные поля (члены)
Внимательный читатель видел, что написано: Класс-наследник имеет поля и функции-члены базового класса
Значит и поле private передается наследнику, но доступа к этому полю внутри класса нету. Выступает такой элемент в качестве виртуального паразита. Ведь для него внутри объекта выделяется память, в которой он зависает и тащится от безделья.
Ответ - Да, но использовать элементы внутри наследника из этих полей нельзя
Вообще много людей говорит и пишет, что приватные поля не наследуются. Не слушайте их. Они категорически неправы. Очень легко показать, что единственный и верный ответ тот, который я уже написал. Демонстрирую кодом
Код C++ private поля наследуются
==========================
#include <conio.h>
#include <iostream.h>
class A
{
int a,b,c; //По умолчанию private.
};
class B:public A //Применили наследование и на основе класса A создали класс B
{
};
class C //Независимый класс
{
};
A obj_A; //Экземпляр класса A
B obj_B; //Экземпляр класса B
C obj_C; //Экземпляр класса С
void main()
{
clrscr();
cout<<sizeof(obj_A)<<endl; //Вывели на экран размер объекта от класса A
cout<<sizeof(obj_B)<<endl; //Вывели на экран размер объекта от класса B
cout<<sizeof(obj_C)<<endl; //Вывели на экран размер объекта от класса C
getch();
return;
}
==========================
Теперь смотрим на код. С одной стороны классы B и C ничего не содержат. Если в класс B ничего не унаследовалось, то B = C = пустой класс. Следовательно размеры объектов от этих классов должны быть равны друг другу. И надо же такому случится, в классе A нет ничего кроме приватных элементов. Вот тут-то и возникает момент истинны.
(obj_A=obj_B или obj_B=obj_C?)
При выводе на экран размеров объектов прекрасно видно, что первые два объекта равны и размер их заметно больше размера третьего объекта. Догадались почему? Потому что эти приватные элементы паразитируют не только виртуально, но и пудрят мозги бедным студентам. Существует только один правильный ответ про наследование приватных элементов по заданному вопросу. Этот ответ - Да, наследуются, висят в памяти, кроме пожирания памяти не делают ничего и использовать их нельзя. Одним словом - Паразиты
C++ для начинающих Знакомство с protected (модификатор доступа внутри класса)
2012-05-07 09:43:00 (читать в оригинале)Всех начинающих интересует вопрос про модификатор доступа protected. Собственно, сам по себе модификатор protected очень похож на private, но используют его при наследовании. Я не могу предвидеть всего, поэтому описать все случаи не смогу, сконцентрируюсь на одном примере.
Так как тема этой статьи может немного запутать читателя, то уточняю
Это статья про protected в качестве модификатора доступа как такового, а не в качествеprotected наследования.
Для хорошего восприяти статьи нужно понимать и ориентироваться в темах:
Функции в С++ для начинающих. Прототипы
Передача параметров в функции в C++ для начинающих (Передается простой)
С++ для начинающих Классы Первое знакомство
С++ для начинающих Классы, простое наследование первое знакомство
С++ для начинающих Определение методов класса вне класса
class A //Класс A - базовый класс, от него будут наследоваться другие
{
protected:
int x;
public:
void show_x(); //Функция отобразит элемент x, описанный в protected этого класса
};
class B:public A //Класс B унаследовал все поля у класса A
{
void get_x(int);
};
{
x=X; // в x класса B записывается параметр передаваемый из основной программы
return;
}
void A::show_x()
{
cout<<"x = "<<x<<endl; //Выводим x из класса A на экран
return;
}
B obj1; //obj1 - экземпляр класса B
void main()
{
clrscr();
int value=10; //Это переменная, которая передается в качестве параметра в метод класса
obj1.get_x(value); //Эстафета: value-->X (класс B) X-->x (класс B);
obj1.show_x(); //На экран выводится x из класса B = 10
getch();
return;
}
=============================
К сожалению комментарии лучше написать я не могу и нужно читать следующие пояснения.
В этой демонстрационной программе был объявлен только один объект, который произошел от производного класса.
В базовом классе присутствует только один элемент и одна функция, которая выполняет вывод этого элемента на экран. При создании класса-наследника, в классе наследнике сразу прописались такие же функции какие были в основном (за это отвечает наследование). + классу наследнику была дописана одна функция сверху. С помощью этой функции в этот единственный (унаследованный от A) элемент присваивается значение. Стоит отметить, что то что добавляется к наследнику, это к основному классу отношения не имеет, так как родитель передает наследнику всё, наследник родителю ничего.
В итоге:
В одном классе один элемент и одна функция
В другом один элемент и две функции
Эти элементы и функции срабатывают персонально для своего класса.
Благодаря тому что я описал переменную x через модификатор доступа protected, внутри всех наследников я могу обращаться к этому x как будто я обращаюсь к нему внутри основного класса и любое такое обращение будет расценено безошибочно и именно для того класса, внутри которого я к этому x обращаюсь.
Если в приведенном примере убрать слово protected, то для x модификатор доступа станет private и компилятор не сможет выполнить код.
Вывод я могу сделать один По сути вышло так, что с помощью protected я абстрагировался от основного класса
Несмотря на то что я смог сделать лишь один вывод, есть и другие моменты в программировании когда protected облегчает код (Не знаю, думаю так)
Так как тема этой статьи может немного запутать читателя, то уточняю
Это статья про protected в качестве модификатора доступа как такового, а не в качестве
Для хорошего восприяти статьи нужно понимать и ориентироваться в темах:
Функции в С++ для начинающих. Прототипы
Передача параметров в функции в C++ для начинающих (Передается простой)
С++ для начинающих Классы Первое знакомство
С++ для начинающих Классы, простое наследование первое знакомство
С++ для начинающих Определение методов класса вне класса
Код С++ Модификатор доступа protected
============================= #include <conio.h>
#include <iostream.h>
class A //Класс A - базовый класс, от него будут наследоваться другие
{
protected:
int x;
public:
void show_x(); //Функция отобразит элемент x, описанный в protected этого класса
};
class B:public A //Класс B унаследовал все поля у класса A
{
void get_x(int);
};
//Идет описание функций из классов вне своих классов
void B::get_x(int X) //Функция из класса B{
x=X; // в x класса B записывается параметр передаваемый из основной программы
return;
}
void A::show_x()
{
cout<<"x = "<<x<<endl; //Выводим x из класса A на экран
return;
}
B obj1; //obj1 - экземпляр класса B
void main()
{
clrscr();
int value=10; //Это переменная, которая передается в качестве параметра в метод класса
obj1.get_x(value); //Эстафета: value-->X (класс B) X-->x (класс B);
obj1.show_x(); //На экран выводится x из класса B = 10
getch();
return;
}
=============================
К сожалению комментарии лучше написать я не могу и нужно читать следующие пояснения.
В этой демонстрационной программе был объявлен только один объект, который произошел от производного класса.
В базовом классе присутствует только один элемент и одна функция, которая выполняет вывод этого элемента на экран. При создании класса-наследника, в классе наследнике сразу прописались такие же функции какие были в основном (за это отвечает наследование). + классу наследнику была дописана одна функция сверху. С помощью этой функции в этот единственный (унаследованный от A) элемент присваивается значение. Стоит отметить, что то что добавляется к наследнику, это к основному классу отношения не имеет, так как родитель передает наследнику всё, наследник родителю ничего.
В итоге:
В одном классе один элемент и одна функция
В другом один элемент и две функции
Эти элементы и функции срабатывают персонально для своего класса.
Благодаря тому что я описал переменную x через модификатор доступа protected, внутри всех наследников я могу обращаться к этому x как будто я обращаюсь к нему внутри основного класса и любое такое обращение будет расценено безошибочно и именно для того класса, внутри которого я к этому x обращаюсь.
Если в приведенном примере убрать слово protected, то для x модификатор доступа станет private и компилятор не сможет выполнить код.
Вывод я могу сделать один По сути вышло так, что с помощью protected я абстрагировался от основного класса
Несмотря на то что я смог сделать лишь один вывод, есть и другие моменты в программировании когда protected облегчает код (Не знаю, думаю так)
Классы, простое наследование первое знакомство
2012-05-05 16:49:00 (читать в оригинале) Точно также как я начинал свой блог с пустой программы, имеет смысл описать пустое наследование. Минимум кода позволит уяснить нужные моменты
class A
{
};
class B: public A; //класс B наследуется из класса A
{
};
A obj1; //obj1 есть объект класса A
B obj2; //obj2 есть объект класса B
void main()
{
return;
}
======================
В приведенном коде созданы два класса, так как сами по себе классы это пустые идеи, то я посчитал нужным объявить объекты. Здесь каждый объект соответствует своему классу и является воплощением идей во что-то реально существующее. Дальше была объявлена главная функция программы. Вот когда я объявил объекты obj1,obj2 - они стали ждать когда я к ним обращусь.
Наследованием называется создание подкласса на основе уже существующего. Для того, чтобы хорошо понять изложенный дальше материал, нужно знать и легко ориентироваться в темах:
Функции в С++ для начинающих. Прототипы
Передача параметров в функции в C++ для начинающих (достаточно передачи обычного)
С++ для начинающих Определение методов класса вне класса
Незнание любого из этих материалов может привести только к потраченному зря времени
class A
{
int x; //x является элементом класса A и доступен только внутри своего класса
public:
void get_x(int); //Прототип функции, через которую в вышеобъявленный x присваивается значение
void show_x(); //Прототип функции, выводящей x на экран
};
class B: public A; //класс B наследуется из класса A
{
};
{
x=X; //x и X различны. т.к. регистр разный. x- элемент класса, в X принимается параметр
return;
}
void A::show()
{
cout<<x<<endl; //Вывод x на экран
}
A obj1; //obj1 есть объект класса A
B obj2; //obj2 есть объект класса B
void main()
{
clrscr();
int value=10; //value будет передаваться в функцию в качестве параметра
obj1.get_x(value); //Эстафета по классу A: value->X X->x
obj1.show(); //x из Класса A выводится на экран
//свойства и функциональность родительского класса заимствуются новым классом
value=20;
obj2.get_x(); //Эстафета по классу B: value->X X->x
obj2.show(); //x из класса B выводится на экран у
getch();
return;
}
============================
В приведенном коде описывается базовый класс A, на основе этого класса описывается второй класс, класс B. Класс A играет роль фундамента и передает все свои тайны своему наследнику.
Внутри класса A объявлен один скрытый элемент x. Этот элемент x объявлен в разделе private класса A (private прописывать не обязательно, так как это доступ по умолчанию). Таким образом, чтобы обратиться к этому x вне класса A нужно использовать посредника, в роли такого посредника выступит метод get_x(int) из класса A Для работы с этим x было объявлено две функции, в одну функцию передается какой-то параметр извне, а внутри этой функции этот параметр записывается в x. Вторая функция выводит этот самый x на экран.
Далее в коде использован прием наследования, и несмотря на то, что внутри класса B ничего не написано, про класс B смело можно сказать то же самое, что только что было описано про класс A. Таким образом базовый класс передал своему наследнику всё что в нем есть, поэтому с объектом B можно обращаться как с объектом типа A.
Коротко так: Если внутри потомка ничего не написано, то Потомок=Родитель
Смысл наследования в том, что потомок = Родитель плюс В потомке есть всё что есть у родителя, но у родителя не всё, что есть у потомка. Родитель щедро делится всем, потомку нужно только наследство (классика жанра)
Код С++ Простое наследование В класс потомок передаются данные из Класса-родителя
============================
class A
{
int x; //x является элементом класса A и доступен только внутри своего класса
public:
void get_x(int); //Прототип функции, через которую в вышеобъявленный x присваивается значение
void show_x(); //Прототип функции, выводящей x на экран
};
class B: public A //класс B наследуется из класса A
{
public:
void show_hello() //В класс-наследник была добавлена функция вывода на экран Hello
{
cout<<"Hello"<<endl;
}
};
{
x=X; //x и X различны. т.к. регистр разный. x- элемент класса, в X принимается параметр
return;
}
void A::show()
{
cout<<x<<endl; //Вывод x на экран
}
A obj1; //obj1 есть объект класса A
B obj2; //obj2 есть объект класса B
void main()
{
clrscr();
int value=10; //value будет передаваться в функцию в качестве параметра
obj1.get_x(value); //Эстафета по классу A: value->X X->x
obj1.show(); //x из Класса A выводится на экран
//свойства и функциональность родительского класса заимствуются новым классом
value=20;
obj2.get_x(); //Эстафета по классу B: value->X X->x
obj2.show(); //x из класса B выводится на экран у
obj1.show_hello(); //Потомок родителю не дает ни копейки, так не выйдет
obj2.show_hello(); //На экран выведется Hello. Это функция из класса B
getch();
return;
}
============================
Этот код очень похож на предыдущий, но внутри наследника дописана одна функция, чтобы было лучше видно, я описал её непосредственно внутри класса. В разделе public я ее описал, чтобы было можно к ней обратится напрямую без заморочек. Внутри потомка можно создать одноименную функцию с функцией из класса родителя, в таком случае происходит что-то вроде отказа от этой части наследства и такая функция становится самостоятельной функцией своего класса. Думаю это можно не демонстрировать, вы сами можете посмотреть поведение программы в такой ситуации.
Функцию которую я добавил я назвал новым именем и внутри нее написал код, выводящий на экран Hello. Таким образом, всё что справедливо для класса A стало справедливым для класса B, но не всё что справедливо для класса B справедливо для класса A
Хочу я этого или не хочу, но придется забежать немного вперед и сообщить важную часть информации. В первом случае был описан пустой класс B, но несмотря на то, что я написал: "он унаследовал все элементы из класса A", об абсолютно полном унаследовании элементов в классы говорить в корне неправильно. На самом деле, во время первого обращения к каждому из объектов, произошел неявный вызов конструктора. Для каждого объекта вызывается исключительно свой конструктор и этот элемент никогда не наследуется. Так как конструкторы создаваемые по умолчанию одинаковые, то в описанном случае верно высказывание Класс А равен классу B, но при этом неверноКласс B унаследовал всё из класса A (имеется ввиду тот случай где в классе B внутри скобок пусто)
Подводим итоги:
Код С++ Простое наследование
======================class A
{
};
class B: public A; //класс B наследуется из класса A
{
};
A obj1; //obj1 есть объект класса A
B obj2; //obj2 есть объект класса B
void main()
{
return;
}
======================
В приведенном коде созданы два класса, так как сами по себе классы это пустые идеи, то я посчитал нужным объявить объекты. Здесь каждый объект соответствует своему классу и является воплощением идей во что-то реально существующее. Дальше была объявлена главная функция программы. Вот когда я объявил объекты obj1,obj2 - они стали ждать когда я к ним обращусь.
Наследованием называется создание подкласса на основе уже существующего. Для того, чтобы хорошо понять изложенный дальше материал, нужно знать и легко ориентироваться в темах:
Функции в С++ для начинающих. Прототипы
Передача параметров в функции в C++ для начинающих (достаточно передачи обычного)
С++ для начинающих Определение методов класса вне класса
Незнание любого из этих материалов может привести только к потраченному зря времени
Код С++ Простое наследование В класс потомок передаются данные из Класса-родителя
============================#include <conio.h>
#include <iostream.h>
class A
{
int x; //x является элементом класса A и доступен только внутри своего класса
public:
void get_x(int); //Прототип функции, через которую в вышеобъявленный x присваивается значение
void show_x(); //Прототип функции, выводящей x на экран
};
class B: public A; //класс B наследуется из класса A
{
};
//Определяю функции из класса вне своего класса.
void A::get_x(int X){
x=X; //x и X различны. т.к. регистр разный. x- элемент класса, в X принимается параметр
return;
}
void A::show()
{
cout<<x<<endl; //Вывод x на экран
}
A obj1; //obj1 есть объект класса A
B obj2; //obj2 есть объект класса B
void main()
{
clrscr();
int value=10; //value будет передаваться в функцию в качестве параметра
obj1.get_x(value); //Эстафета по классу A: value->X X->x
obj1.show(); //x из Класса A выводится на экран
//свойства и функциональность родительского класса заимствуются новым классом
value=20;
obj2.get_x(); //Эстафета по классу B: value->X X->x
obj2.show(); //x из класса B выводится на экран у
getch();
return;
}
============================
В приведенном коде описывается базовый класс A, на основе этого класса описывается второй класс, класс B. Класс A играет роль фундамента и передает все свои тайны своему наследнику.
Внутри класса A объявлен один скрытый элемент x. Этот элемент x объявлен в разделе private класса A (private прописывать не обязательно, так как это доступ по умолчанию). Таким образом, чтобы обратиться к этому x вне класса A нужно использовать посредника, в роли такого посредника выступит метод get_x(int) из класса A Для работы с этим x было объявлено две функции, в одну функцию передается какой-то параметр извне, а внутри этой функции этот параметр записывается в x. Вторая функция выводит этот самый x на экран.
Далее в коде использован прием наследования, и несмотря на то, что внутри класса B ничего не написано, про класс B смело можно сказать то же самое, что только что было описано про класс A. Таким образом базовый класс передал своему наследнику всё что в нем есть, поэтому с объектом B можно обращаться как с объектом типа A.
Коротко так: Если внутри потомка ничего не написано, то Потомок=Родитель
Смысл наследования в том, что потомок = Родитель плюс В потомке есть всё что есть у родителя, но у родителя не всё, что есть у потомка. Родитель щедро делится всем, потомку нужно только наследство (классика жанра)
Код С++ Простое наследование В класс потомок передаются данные из Класса-родителя
============================
#include <conio.h>
#include <iostream.h>
class A
{
int x; //x является элементом класса A и доступен только внутри своего класса
public:
void get_x(int); //Прототип функции, через которую в вышеобъявленный x присваивается значение
void show_x(); //Прототип функции, выводящей x на экран
};
class B: public A //класс B наследуется из класса A
{
public:
void show_hello() //В класс-наследник была добавлена функция вывода на экран Hello
{
cout<<"Hello"<<endl;
}
};
//Определяю функции из класса вне своего класса.
void A::get_x(int X){
x=X; //x и X различны. т.к. регистр разный. x- элемент класса, в X принимается параметр
return;
}
void A::show()
{
cout<<x<<endl; //Вывод x на экран
}
A obj1; //obj1 есть объект класса A
B obj2; //obj2 есть объект класса B
void main()
{
clrscr();
int value=10; //value будет передаваться в функцию в качестве параметра
obj1.get_x(value); //Эстафета по классу A: value->X X->x
obj1.show(); //x из Класса A выводится на экран
//свойства и функциональность родительского класса заимствуются новым классом
value=20;
obj2.get_x(); //Эстафета по классу B: value->X X->x
obj2.show(); //x из класса B выводится на экран у
obj2.show_hello(); //На экран выведется Hello. Это функция из класса B
getch();
return;
}
============================
Этот код очень похож на предыдущий, но внутри наследника дописана одна функция, чтобы было лучше видно, я описал её непосредственно внутри класса. В разделе public я ее описал, чтобы было можно к ней обратится напрямую без заморочек. Внутри потомка можно создать одноименную функцию с функцией из класса родителя, в таком случае происходит что-то вроде отказа от этой части наследства и такая функция становится самостоятельной функцией своего класса. Думаю это можно не демонстрировать, вы сами можете посмотреть поведение программы в такой ситуации.
Функцию которую я добавил я назвал новым именем и внутри нее написал код, выводящий на экран Hello. Таким образом, всё что справедливо для класса A стало справедливым для класса B, но не всё что справедливо для класса B справедливо для класса A
Хочу я этого или не хочу, но придется забежать немного вперед и сообщить важную часть информации. В первом случае был описан пустой класс B, но несмотря на то, что я написал: "он унаследовал все элементы из класса A", об абсолютно полном унаследовании элементов в классы говорить в корне неправильно. На самом деле, во время первого обращения к каждому из объектов, произошел неявный вызов конструктора. Для каждого объекта вызывается исключительно свой конструктор и этот элемент никогда не наследуется. Так как конструкторы создаваемые по умолчанию одинаковые, то в описанном случае верно высказывание Класс А равен классу B, но при этом неверно
Подводим итоги:
- Наследование - создание подкласса на основе уже существующего
- Класс от которого произошло наследование называется базовым или родителем
- Класс, который произошел от родителя называется производным классом или потомком
- Наследование похоже на доведение чего-то готового до ума через добавление дополнительной функциональности
- Конструкция наследования class ИмяКлассаРодителя: метод доступа ИмяКлассаПотомка {методы потомка};
- При использовании наследования свойства и функциональность родительского класса заимствуются классом-потомком
- В случае если в класс потомок добавлены какие-то элементы, то класс потомок не делится этим с родителем
- При использовании в методах класса-потомка , одноименного метода с методом класса-родителя происходит что-то вроде отказа от этой части наследования и такой метод воспринимается классом потомком как самостоятельный и свой собственный метод
- Несмотря на то, что класс потомок может быть равен классу-родителю, Нет и не может быть такого случая когда можно сказать, что класс потомок унаследовал абсолютно всё от класса родителя (прим. В контексте этого вывода: Для работы с классом обязателен объект)
Enum как работать и зачем нужно
2012-05-03 21:48:00 (читать в оригинале)Что такое enum, зачем нужен enum и другие вопросы по слову enum могут возникнуть при разработке ваших программ и изучении чужих кодов.
enum - Это тип перечисление.
В enum записываются константы и каждой новой константе присваивается порядковый номер, чтобы было понятно привожу код C++
#include <conio.h>
boolean flag; //flag есть переменная типа перечисления boolean
void main()
{
clrscr();
flag=0; //перечисление flag обращается к своему нулевому элементу, flag=false=0;
cout<<flag<<endl; //нулевой элемент перечисления это false, но на экран выводится номер элемента
flag=1; //перечисление flag обращается к своему первому элементу, flag=true=1;
cout<<flag<<endl; //первый элемент перечисления это true, но на экран выводится номер элемента
getch();
return;
}
===================
В общем, прямым путем вытащить можно только номер элемента, а не строковое значение переменной типа enum. Такой вариант используется если требуется сравнить значения с константами и на основе результатов сравнений создать свое поведение программы. Для хорошего восприятия приведу код
В программе задается один вопрос и пользователь должен ввести ответ. На основе правильности ответа программа срабатывает по разному
void main()
{
clrscr();
enum boolean {true,false} //=Верно и Неверно
boolean flag; //flag есть переменная типа boolean
cout<<"2+2 = "; //Вывели вопрос на экран
int ch; //В переменную ch , будем заносить ответ
cin>>ch; //Присвоили в ch введенный ответ
/*Возможны два варианта обращения к перечислению*/
if (ch==4) {flag=true;} //если ввели 4, то flag=true=0
else {flag=false;} //в противном случае flag=false=1
//то же самое можно написать так
if (ch==4) {flag=0;} //если ввели 4, то flag=0
else {flag=1} //в противном случае flag=1
getch();
return;
}
====================
Здесь показано, что к перечислению можно обращаться двумя способами.
Бывает, что нужно вытащить строковое значение enum по номеру элемента. Напрямую такую операцию выполнить не получится, поэтому приходится использовать обходной путь. Так как enum содержит набор констант, то этот enum можно рассматривать как одномерный массив. Определять массив придется независимо от enum, значения в него прописать точно также как в enum
Код С++ Вытащить строковое значение из enum
==========================
void main()
{
clrscr();
enum boolean {true,false}; //boolean -тип перечисление
boolean flag; //flag переменная типа boolean
flag=0; // Явное привидение flag=0;
cout<<flag_name[flag]; //Обращение к массиву по индексу flag Нулевой элемент массива= true
cout<<endl;
flag=1; //Явное привидение flag=1;
cout<<flag_name[flag]; //Обращение к массиву по индексу flag. Первый элемент массива = false
cout<<endl;
cout<<flag_name[flag]; //Обращение к массиву по индексу flag Нулевой элемент массива= true
cout<<endl;
flag=false; //Неявное привидение flag=false=1; cout<<flag_name[flag]; //Обращение к массиву по индексу flag. Первый элемент массива= false
//Выводим все строковые значения на экран
for (i=0;i<1;i++)
{
cout<<flag_name[i]<<" "; //Для вывода на экран мы обращаемся к массиву.
}
getch();
return;
}
==========================
Чтобы легче усвоить этот код, нужно хорошо понять ранее приведенный. К тому что я уже писал могу добавить, что для работы со строковыми значениями из enum нет никакого обращение к enum, вместо этого мы обращаемся к отдельному самостоятельному объекту, к массиву, который создали. В последней части кода выполняется цикл, с помощью которого выводятся все значения из нашего массива. А так как значения, записанные в массив равны значениям из enum и порядок у них такой же, то такая запись абсолютна эквивалентна выводу всех строковых значений из перечисления.
Надеюсь, что то что я решил в качестве подопытного объекта взять тип boolean и создать его своими силами - правильный подход к разъяснениям. Количество констант может быть и три и четыре и одна, это определяете вы.
Как вы не можете обозвать константу русскими буквами внутри программы, так же вы не можете обозвать русскими буквами константу внутри перечисляемого типа. Константа есть константа.
Можно переназначить первый порядковые номера в enum. По умолчанию это ноль.
enum boolean {true=100,false} // Теперь порядковый номер true=100, false=101;
enum - Это тип перечисление.
В enum записываются константы и каждой новой константе присваивается порядковый номер, чтобы было понятно привожу код C++
C++ enum
===================#include <conio.h>
#include <iostream.h>
enum boolean {false,true}; // Перечислили две константы false и trueboolean flag; //flag есть переменная типа перечисления boolean
void main()
{
clrscr();
flag=0; //перечисление flag обращается к своему нулевому элементу, flag=false=0;
cout<<flag<<endl; //нулевой элемент перечисления это false, но на экран выводится номер элемента
flag=1; //перечисление flag обращается к своему первому элементу, flag=true=1;
cout<<flag<<endl; //первый элемент перечисления это true, но на экран выводится номер элемента
getch();
return;
}
===================
В общем, прямым путем вытащить можно только номер элемента, а не строковое значение переменной типа enum. Такой вариант используется если требуется сравнить значения с константами и на основе результатов сравнений создать свое поведение программы. Для хорошего восприятия приведу код
В программе задается один вопрос и пользователь должен ввести ответ. На основе правильности ответа программа срабатывает по разному
Код С++ enum
==================== #include <conio.h>
#include <iostream.h>
void main()
{
clrscr();
enum boolean {true,false} //=Верно и Неверно
boolean flag; //flag есть переменная типа boolean
cout<<"2+2 = "; //Вывели вопрос на экран
int ch; //В переменную ch , будем заносить ответ
cin>>ch; //Присвоили в ch введенный ответ
/*Возможны два варианта обращения к перечислению*/
if (ch==4) {flag=true;} //если ввели 4, то flag=true=0
else {flag=false;} //в противном случае flag=false=1
//то же самое можно написать так
if (ch==4) {flag=0;} //если ввели 4, то flag=0
else {flag=1} //в противном случае flag=1
getch();
return;
}
====================
Здесь показано, что к перечислению можно обращаться двумя способами.
- В первом случае обращение идет к имени константы
- Во втором случае обращение идет к номеру константы
Бывает, что нужно вытащить строковое значение enum по номеру элемента. Напрямую такую операцию выполнить не получится, поэтому приходится использовать обходной путь. Так как enum содержит набор констант, то этот enum можно рассматривать как одномерный массив. Определять массив придется независимо от enum, значения в него прописать точно также как в enum
Код С++ Вытащить строковое значение из enum
==========================
#include <conio.h>
#include <iostream.h>
void main()
{
clrscr();
enum boolean {true,false}; //boolean -тип перечисление
boolean flag; //flag переменная типа boolean
//Создадим массив, похожий по внутреннему представлению на enum boolean
char *flag_name[ ]={"true","false"}; //не enum, но оочень похожая запись/* Ниже представлены 2 варианта обращения к Enum, аналогично предыдущему коду, но обращаться мы будем не к enum, а к массиву, который определяли независимо и отдельно от enum */
//Обращаемся по порядковому номеруflag=0; // Явное привидение flag=0;
cout<<flag_name[flag]; //Обращение к массиву по индексу flag Нулевой элемент массива= true
cout<<endl;
flag=1; //Явное привидение flag=1;
cout<<flag_name[flag]; //Обращение к массиву по индексу flag. Первый элемент массива = false
cout<<endl;
//Обращаемся по имени константы
flag=true; //Неявное приведение. flag=true=0;cout<<flag_name[flag]; //Обращение к массиву по индексу flag Нулевой элемент массива= true
cout<<endl;
flag=false; //Неявное привидение flag=false=1; cout<<flag_name[flag]; //Обращение к массиву по индексу flag. Первый элемент массива= false
//Выводим все строковые значения на экран
for (i=0;i<1;i++)
{
cout<<flag_name[i]<<" "; //Для вывода на экран мы обращаемся к массиву.
}
getch();
return;
}
==========================
Чтобы легче усвоить этот код, нужно хорошо понять ранее приведенный. К тому что я уже писал могу добавить, что для работы со строковыми значениями из enum нет никакого обращение к enum, вместо этого мы обращаемся к отдельному самостоятельному объекту, к массиву, который создали. В последней части кода выполняется цикл, с помощью которого выводятся все значения из нашего массива. А так как значения, записанные в массив равны значениям из enum и порядок у них такой же, то такая запись абсолютна эквивалентна выводу всех строковых значений из перечисления.
Надеюсь, что то что я решил в качестве подопытного объекта взять тип boolean и создать его своими силами - правильный подход к разъяснениям. Количество констант может быть и три и четыре и одна, это определяете вы.
Как вы не можете обозвать константу русскими буквами внутри программы, так же вы не можете обозвать русскими буквами константу внутри перечисляемого типа. Константа есть константа.
Можно переназначить первый порядковые номера в enum. По умолчанию это ноль.
enum boolean {true=100,false} // Теперь порядковый номер true=100, false=101;
- Использование перечислений позволяет сделать исходные коды программ более читаемыми
- При обращении к переменной типа перечисление по имени константы происходит неявное привидение к int
- Одной из причин использования enum является экономия памяти
- С точки зрения обеспечения удобочитаемости программ ничто не мешает вместо перечислимого типа использовать просто группу совместно определённых именованных констант, особенно при наличии таких языковых механизмов, как модули или классы
Передача параметров в функции в C++ для начинающих
2012-05-03 13:37:00 (читать в оригинале)Передача параметров в функции в C++ для начинающих крайне важная информация. Я стараюсь не собирать всё в кучу, поэтому в этой статье будет выложен материал по теме только частично.
В этой статье я опишу чем отличается передача обычного параметра в функцию от передачи параметра в функцию в виде ссылки или от параметра в виде указателя. Чтобы было понятно нужно привести пример
#include <conio.h>
int sum_ref(int &); //Функция будет принимать ссылку
int sum_ptr(int *); //Функция будет принимать указатель
//Определяем функции. 3 функции по прототипам + main
int sum_value(int x) //В переменную x присваивается значение извне. x- обычный параметр
{
x=x+1; //x увеличивается на один
return x; //возвращаем полученный x
}
int sum_ref(int &x) //В функцию передается ссылка, она ссылается на объект извне
{
x=x+1; //Увеличили x на один
return x; //возвращаем полученный x
}
int sum_ptr(int *x) //В функцию передается указатель. Указатель это адрес переменной извне
{
*x=*x+1; //Для того, чтоб работать с указателем как с переменной, нужно его разыменовать
return *x; //Если не прописать звездочки, будет выведен адрес, а не значение объекта
}
{
clrscr();
int value=10; //Переменная value будет выступит передаваемым параметром в функцию
cout<<sum_value(value)<<endl; //Первое обращение. Передача в функцию обычного параметра
cout<<value<<endl<<endl;
cout<<sum_ref(value)<<endl; //Второе обращение. Передача в функцию параметра ссылки
cout<<value<<endl<<endl;
cout<<sum_ptr(&value)<<endl; //Третье обращение. Передача в функцию параметра указателя
cout<<value<<endl<<endl;
getch();
return;
}
============================
При первом обращении в функцию передается параметр, равный value. Внутри функции этот параметр как эстафетную палочку принимает переменная x и вся обработка идет с этим x, а сама переменная value тихо отходит курить в сторонку "Вдруг пригожусь" При этом переменная x является локальной переменной, т.к. объявлена внутри функции, а значит всё что происходит с ней, всё происходит только в пределах этой функции. При попытке вывести на экран value - value снова играет главную роль, но она же просто курила в сторонке и никто ее не трогал. Как было ей присвоено 10, так и осталось
При втором обращении в качестве параметра передается ссылка. Так обращение к ссылке точно такое же как обращение к переменной, то такой вызов совершенно такой же как и первый, НО сама работа программы при таком вызове происходит по другому. Так как функция принимает параметр в качестве ссылки, то получается что-то типа Ссылка говорит объекту: "Тебе надо, ты и делай". Т.е. выходит так, что в отличие от первого варианта, объект только собрался курить в сторонке, а ссылка ему сразу пинком под зад: "Я курить, а если ничего не сделаем звездюлей тебе вешать будут". В общем получается, что value теперь как входной, так и выходной параметр. При попытке вывода на экран выведется 11, потому что обрабатываться будет сам параметр, а не ссылка на него
Третий вариант по работе точно такой же как и второй, только сам вызов происходит немного по другому. Так как указатель сам по себе адрес переменной, то в вызове функции идет обращение к адресу параметра. Внутри функции использовано разыменование, так как для работы с самим объектом нужно это самое разыменование.
Что я еще могу сказать. Первый вариант можно привести ко второму или третьему, если например, объявить глобальную переменную (int z), после этого внутри функции присвоить в нее полученную x, а после вызова функции из тела программы написать value=x., а оно надо? можно еще написать value=sum_value(value) , но удобнее использовать ссылки
В этой статье я опишу чем отличается передача обычного параметра в функцию от передачи параметра в функцию в виде ссылки или от параметра в виде указателя. Чтобы было понятно нужно привести пример
Код C++ Передача параметров в функции Обычный, Ссылка, Указатель
============================#include <conio.h>
#include <iostream.h>
//Определяем прототипы функций
int sum_value(int); //Функция будет принимать обычный параметрint sum_ref(int &); //Функция будет принимать ссылку
int sum_ptr(int *); //Функция будет принимать указатель
//Определяем функции. 3 функции по прототипам + main
int sum_value(int x) //В переменную x присваивается значение извне. x- обычный параметр
{
x=x+1; //x увеличивается на один
return x; //возвращаем полученный x
}
int sum_ref(int &x) //В функцию передается ссылка, она ссылается на объект извне
{
x=x+1; //Увеличили x на один
return x; //возвращаем полученный x
}
int sum_ptr(int *x) //В функцию передается указатель. Указатель это адрес переменной извне
{
*x=*x+1; //Для того, чтоб работать с указателем как с переменной, нужно его разыменовать
return *x; //Если не прописать звездочки, будет выведен адрес, а не значение объекта
}
//Внутри функции main функции вызываются по очереди
void main(){
clrscr();
int value=10; //Переменная value будет выступит передаваемым параметром в функцию
cout<<sum_value(value)<<endl; //Первое обращение. Передача в функцию обычного параметра
cout<<value<<endl<<endl;
cout<<sum_ref(value)<<endl; //Второе обращение. Передача в функцию параметра ссылки
cout<<value<<endl<<endl;
cout<<sum_ptr(&value)<<endl; //Третье обращение. Передача в функцию параметра указателя
cout<<value<<endl<<endl;
getch();
return;
}
============================
При первом обращении в функцию передается параметр, равный value. Внутри функции этот параметр как эстафетную палочку принимает переменная x и вся обработка идет с этим x, а сама переменная value тихо отходит курить в сторонку "Вдруг пригожусь" При этом переменная x является локальной переменной, т.к. объявлена внутри функции, а значит всё что происходит с ней, всё происходит только в пределах этой функции. При попытке вывести на экран value - value снова играет главную роль, но она же просто курила в сторонке и никто ее не трогал. Как было ей присвоено 10, так и осталось
При втором обращении в качестве параметра передается ссылка. Так обращение к ссылке точно такое же как обращение к переменной, то такой вызов совершенно такой же как и первый, НО сама работа программы при таком вызове происходит по другому. Так как функция принимает параметр в качестве ссылки, то получается что-то типа Ссылка говорит объекту: "Тебе надо, ты и делай". Т.е. выходит так, что в отличие от первого варианта, объект только собрался курить в сторонке, а ссылка ему сразу пинком под зад: "Я курить, а если ничего не сделаем звездюлей тебе вешать будут". В общем получается, что value теперь как входной, так и выходной параметр. При попытке вывода на экран выведется 11, потому что обрабатываться будет сам параметр, а не ссылка на него
Третий вариант по работе точно такой же как и второй, только сам вызов происходит немного по другому. Так как указатель сам по себе адрес переменной, то в вызове функции идет обращение к адресу параметра. Внутри функции использовано разыменование, так как для работы с самим объектом нужно это самое разыменование.
Что я еще могу сказать. Первый вариант можно привести ко второму или третьему, если например, объявить глобальную переменную (int z), после этого внутри функции присвоить в нее полученную x, а после вызова функции из тела программы написать value=x., а оно надо? можно еще написать value=sum_value(value) , но удобнее использовать ссылки
- Передача обычного параметра в функцию = входной параметр
- Передача в функцию ссылки/указателя = как входной, так и выходной параметр
Говорят, что основное назначение ссылки заключается в упрощении процесса изменения параметров внутри функции. Мне кажется, что доброй половине начинающих такая фраза совершенно ни о чем
Я бы говорил так: основное назначение ссылки упростить изменение параметра передаваемого в функцию, изменяя принимаемый параметр вне функции, но обрабатывая его внутри неё.
Категория «Обзоры»
Взлеты Топ 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 не имеет отношения к публикуемым в записях блогов материалам. Все записи
взяты из открытых общедоступных источников и являются собственностью их авторов.
взяты из открытых общедоступных источников и являются собственностью их авторов.
