<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C, PHP, VB, .NET &#187; С/C++</title>
	<atom:link href="http://www.cphpvb.net/category/pik-3/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cphpvb.net</link>
	<description>дневникът на Филип Петров</description>
	<lastBuildDate>Mon, 30 Jan 2012 16:44:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Внимание с адреси към локални променливи</title>
		<link>http://www.cphpvb.net/pik-3/4571-%d0%b2%d0%bd%d0%b8%d0%bc%d0%b0%d0%b2%d0%b0%d0%b9%d1%82%d0%b5-%d1%81-%d0%b0%d0%b4%d1%80%d0%b5%d1%81%d0%b8-%d0%ba%d1%8a%d0%bc-%d0%bb%d0%be%d0%ba%d0%b0%d0%bb%d0%bd%d0%b8-%d0%bf%d1%80%d0%be%d0%bc%d0%b5/</link>
		<comments>http://www.cphpvb.net/pik-3/4571-%d0%b2%d0%bd%d0%b8%d0%bc%d0%b0%d0%b2%d0%b0%d0%b9%d1%82%d0%b5-%d1%81-%d0%b0%d0%b4%d1%80%d0%b5%d1%81%d0%b8-%d0%ba%d1%8a%d0%bc-%d0%bb%d0%be%d0%ba%d0%b0%d0%bb%d0%bd%d0%b8-%d0%bf%d1%80%d0%be%d0%bc%d0%b5/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 21:20:25 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=4571</guid>
		<description><![CDATA[Съвсем наскоро ми се наложи да оправям много странен бъг в една програма, която ми я прати студент. Накратко &#8211; функция на С връщаше адрес към локална променлива. Програмата си работеше перфектно, но&#8230; до един момент, в който се записваше нещо ново в стека. Естествено кодът беше достатъчно объркан и зле документиран, а и аз [...]]]></description>
			<content:encoded><![CDATA[<p>Съвсем наскоро ми се наложи да оправям много странен бъг в една програма, която ми я прати студент. Накратко &#8211; функция на С връщаше адрес към локална променлива. Програмата си работеше перфектно, но&#8230; до един момент, в който се записваше нещо ново в стека. Естествено кодът беше достатъчно объркан и зле документиран, а и аз се бях &#8222;облъчил&#8220; с <a href="http://www.cphpvb.net/category/java/" target="_blank">Java</a> и ми беше трудно да превключа на &#8222;вълна C&#8220;. Радвам се обаче, че успях да открия грешката. Съставих и един примерен модел на това, от което трябва да се пазите много, когато работите с указатели:<span id="more-4571"></span></p>
<pre>#include "stdafx.h"
#include "stdio.h"

int* getval()
{
	// създаваме локална променлива
	int x=1;
	// Връщаме адреса й - това е проблема!
	// Такава грешка може да се направи например
	// когато правим някакви временни изчисления.
	return &amp;x;
}

// Функция, която "не прави нищо"
void dummyFunc()
{
	int x=2;
}

int main()
{
	int *p;
	p = getval();
	printf ("*p = %d\n", *p);
	dummyFunc();
	printf ("*p = %d\n", *p);
	return 0;
}</pre>
<p>Изпълнението на горният код &#8222;изненадващо&#8220; е:</p>
<pre>*p = 1
*p = 2</pre>
<p>Интересното е, че в горния пример компилаторът много добре се ориентира и връща warning:</p>
<pre>warning C4172: returning address of local variable or temporary</pre>
<p>При въпросната задача студентът много добре беше замаскирал действието и компилаторът не връщаше никакви предупреждения. Отне ми цяла вечер :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/4571-%d0%b2%d0%bd%d0%b8%d0%bc%d0%b0%d0%b2%d0%b0%d0%b9%d1%82%d0%b5-%d1%81-%d0%b0%d0%b4%d1%80%d0%b5%d1%81%d0%b8-%d0%ba%d1%8a%d0%bc-%d0%bb%d0%be%d0%ba%d0%b0%d0%bb%d0%bd%d0%b8-%d0%bf%d1%80%d0%be%d0%bc%d0%b5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Вектори (std::vector)</title>
		<link>http://www.cphpvb.net/pik-3/301-%d0%b2%d0%b5%d0%ba%d1%82%d0%be%d1%80%d0%b8-stdvector/</link>
		<comments>http://www.cphpvb.net/pik-3/301-%d0%b2%d0%b5%d0%ba%d1%82%d0%be%d1%80%d0%b8-stdvector/#comments</comments>
		<pubDate>Sat, 29 Nov 2008 12:35:30 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=301</guid>
		<description><![CDATA[Досега се стараехме да не използваме готови библиотеки, класове и обекти. За шаблонният клас vector обаче си заслужава да се отдели специално внимание. Векторите са изключително удобен и ефективен заместител на стандартните масиви, като значително спестява ресурси при редица операции. Чрез него имаме възможност за създаване на т.нар. &#8222;динамични масиви&#8220;. Първата стъпка е да прибавим [...]]]></description>
			<content:encoded><![CDATA[<p>Досега се стараехме да не използваме готови библиотеки, класове и обекти. За шаблонният клас vector обаче си заслужава да се отдели специално внимание. Векторите са изключително удобен и ефективен заместител на стандартните масиви, като значително спестява ресурси при редица операции. Чрез него имаме възможност за създаване на т.нар. &#8222;динамични масиви&#8220;.</p>
<p>Първата стъпка е да прибавим класа чрез #include. Вектор се дефинира по следния начин:</p>
<pre>	#include &lt;vector&gt;
	//...
	std::vector&lt;тип&gt; v;</pre>
<p>Синтаксисът изисква указване на типа елементи във вектора. Често е удобно да използваме typedef при дефиниране на вектори. Например:<span id="more-301"></span></p>
<pre>	typedef std::vector&lt;int&gt; int_vec;
	int_vec v1, v2;</pre>
<p>Така например създадохме вектор с елементи от тип int. Използването му по-нататък е много сходно с това на масивите. Ето например как създаваме вектор от 10 елемента, и запълваме елементите му с числата от 1 до 10:</p>
<pre>	std::vector&lt;int&gt; v(10);
	for(int i=0; i&lt;10; i++) v[i] = i+1;</pre>
<p>Виждате, че в класът вектор е предефиниран операторът []. Аналогично действа член-функцията at(int):</p>
<pre>	v.at(1000) = 5;</pre>
<p>Ако елемент с такъв индекс не съществува, то ще бъде върнат обект от тип std::out_of_range. Ще разгледаме подробно как може да бъде използван в тема за обработка на грешки. Съществена разлика между [int] и .at(int) се явява ако сте насочили указател към вектор. При използване на [] то е възможно векторът да се премести на нов адрес (например при разширение, което ще покажем по-долу) и така указателят ви да сочи на грешна позиция. При функцията at този проблем не съществува, тъй като тя работи с фиксиран размер на вектора. Поради тази причина бъдете особено внимателни при използването на указатели към вектор.</p>
<p>Дефиниран е и операторът =:</p>
<pre>	std::vector&lt;int&gt; v2(10);
	v2 = v;</pre>
<p>Две член функции begin и end връщат адреса на началото и края на вектора. Използват се ефективно при употребата на interator. Следният пример демонстрира обхождането на вектор и отпечатването му на екрана:</p>
<pre>	vector&lt;int&gt;::iterator it;
	std::cout &lt;&lt; "v contains:";
	for (it=v.begin(); it&lt;v.end();it++ ){
		std::cout &lt;&lt; " " &lt;&lt; *it;
	}</pre>
<p>Принципно можете да пъстигнете абсолютно същия ефект чрез използването на .at или [] и обхождане на вектора чрез указатели. Въпреки това свикването за използване на iterator се насърчава, тъй като ще е значително по-лесно да го използвате при стандартни алгоритми като сортиране например, тъй като член-функция за тази цел не се предлага, а я има реализирана като шаблонна функция.</p>
<p>Дотук не показахме нищо значително ново в сравнение с обикновените масиви. Нека да разгледаме следния случай &#8211; представете си, че имаме масив, в който записваме динамично данни. В един момент може да се окаже, че масива се е запълнил и нямаме достатъчно място. Векторите решават този проблем:</p>
<pre>	#include "stdafx.h"
	#include &lt;vector&gt;
	#include &lt;iostream&gt;
	using namespace std;

	void main(){
		// Дефинираме празен вектор
		vector&lt;int&gt; v;
		// Функцията size() показва броя елементи на вектора
		cout &lt;&lt; "initial: " &lt;&lt; v.size() &lt;&lt; endl;
		// Чрез push_back можем да добавим елемент
		v.push_back(12);
		cout &lt;&lt; "after I add one element: " &lt;&lt; v.size() &lt;&lt; endl;
		// Добавяме още 10 елемента
		for (int i=0; i&lt;10; i++) v.push_back(i);
		cout &lt;&lt; "after I add 10 more: " &lt;&lt; v.size() &lt;&lt; endl;

		// Отпечатваме съдържанието на вектора
		cout &lt;&lt; "the array contents are:";
		for (i=0; i&lt;v.size(); i++) cout &lt;&lt; " " &lt;&lt; v[i];
		cout &lt;&lt; endl;

	}</pre>
<p>Виждате, че функцията push_back добавя елемент в края на вектора. Тук демонстрирахме и създаването на празен вектор (в предишните примери резервирахме памет за поне десет елемента), както и член-функцията size. Често се използват още две функции &#8211; capacity и max_size. Проверете резултатът от следния пример</p>
<pre>	#include "stdafx.h"
	#include &lt;vector&gt;
	#include &lt;iostream&gt;
	using namespace std;

	void main(){
		vector&lt;int&gt; v;

  		for (int i=0; i&lt;100; i++) v.push_back(i);

		cout &lt;&lt; "size: " &lt;&lt; (int) v.size() &lt;&lt; endl;
		cout &lt;&lt; "capacity: " &lt;&lt; (int) v.capacity() &lt;&lt; endl;
		cout &lt;&lt; "max_size: " &lt;&lt; (int) v.max_size() &lt;&lt; endl;
	}</pre>
<p>Ще забележите, че size връща текущия брой елементи записани във вектора, capacity показва памет за колко елемента е резервирана (т.е. векторът може по подразбиране да задели повече памет отколкото използваме!), а max_size определя максималният в момента свободен блок памет, който може да бъде заделен за нашият вектор. Ако искаме да резервираме допълнително памет (да увеличим capacity), то можем да използваме функцията reserve:</p>
<pre>	v.reserve(200);
	cout &lt;&lt; "now capacity is: " &lt;&lt; (int) v.capacity() &lt;&lt; endl;</pre>
<p>Ако подадем по-малка стойност на reserve отколкото е текущия capacity, то функцията няма да направи нищо. С resize обаче можем да &#8222;изрязваме&#8220; елементи от вектор:</p>
<pre>	v.resize(12);
	cout &lt;&lt; "size: " &lt;&lt; (int) v.size() &lt;&lt; endl;
	cout &lt;&lt; "capacity: " &lt;&lt; (int) v.capacity() &lt;&lt; endl;
	cout &lt;&lt; "max_size: " &lt;&lt; (int) v.max_size() &lt;&lt; endl;</pre>
<p>Изпълнете примера и отпечатайте съдържанието на вектора. Ще видите, че capacity се е запазило, но size е станал 12 и всички елементи след този с индекс 11 са изтрити. Нека сега да извикаме resize чрез втория му конструктор:</p>
<pre>	v.resize(20, 5);</pre>
<p>По този начин добавихме 8 елемента със стойност числото 5 в края на вектора. Това е просто по-лесен начин за добавяне на множество еднакви елементи. Като бързина в сравнение с push_back няма почти никаква разлика.</p>
<p>Вече споменахме функцията at(int). Други две функции, които можем да използваме са front() и back(), чрез които достъпваме съответно първия и последния елемент на вектор. Друга полезна функция е empty(). Тя връща 0 ако в масива има елементи и true ако векторът е празен. Използва се като еквивалент на size()==0.</p>
<p>Много ценна възможност на векторите е да ги използваме за реализацията на структурата стек. Вече се запознахте с функцията push_back, която практически добавя елемент в края на стек. В класа vector са се погрижили и за функция за премахване на елемент от стек:</p>
<pre>	v.pop_back();</pre>
<p>Така просто изтриваме последния елемент на вектора. Имайте в предвид, че тя ще намали size(), но не и capacity().</p>
<p>Накрая една изключително силна възможност на векторите, е тяхната функционалност на структура от тип списък, а именно: вмъкване и изтриване на елементи във вектора. За целта е нужно използването на iterator:</p>
<pre>	#include "stdafx.h"
	#include &lt;iostream&gt;
	#include &lt;vector&gt;
	using namespace std;

	void showvector(vector&lt;int&gt; &amp;v){
		if (v.empty()) cout &lt;&lt; "empty vector" &lt;&lt; endl;
		else{
			vector&lt;int&gt;::iterator it;
			for (it=v.begin(); it&lt;v.end();it++ ){
				cout &lt;&lt; " " &lt;&lt; *it;
			}
		}
		cout &lt;&lt; endl;
	}

	int main (){
		// създава вектор от три елемента
		// всеки от които със стойност 5
		vector&lt;int&gt; v(3,5);
		// добавяме още три елемента
		v.push_back(10);
		v.push_back(11);
		v.push_back(12);
		// показва елементите на вектора
		showvector(v);

		vector&lt;int&gt;::iterator it;
		// накочваме инетатора към 5ти елемент
		it = v.begin()+4;
		// добавяме числото 33 като пети елемент
		v.insert(it, 33);
		showvector(v);

		// създаваме втори вектор
		vector&lt;int&gt; v2(0);
		v2.push_back(999);
		v2.push_back(999);

		// насочваме итератора към трети елемент
		it = v.begin()+2;
		// вмъкваме вектор v2 преди трети елемент на v
		v.insert(it, v2.begin(), v2.end());
		showvector(v);

		// изтриваме 6ти елемент
		it = v.begin() + 5;
		v.erase(it);
		showvector(v);

		// изтриваме елементите от 3ти до 7ми включително
		it = v.begin();
		v.erase(it+2, it + 7);
		showvector(v);

		// разменяме съдържанието на двата вектора
		cout &lt;&lt; "the vectors are:" &lt;&lt; endl;
		showvector(v);
		showvector(v2);
		cout &lt;&lt; "swapped" &lt;&lt; endl;
		v.swap(v2);
		showvector(v);
		showvector(v2);

		// изтриваме съдържанието на вектор
		v.clear();
		showvector(v);

		return 0;
	}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/301-%d0%b2%d0%b5%d0%ba%d1%82%d0%be%d1%80%d0%b8-stdvector/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Шаблони</title>
		<link>http://www.cphpvb.net/pik-3/298-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd%d0%b8/</link>
		<comments>http://www.cphpvb.net/pik-3/298-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd%d0%b8/#comments</comments>
		<pubDate>Sat, 29 Nov 2008 12:33:59 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=298</guid>
		<description><![CDATA[Шаблоните помагат когато искаме да напишем универсална функция, която да може да работи с всякакви типове данни. Синтаксисът е следния: template &#60;class &#60;име-на-класа&#62;&#62;; &#60;декларация на функция&#62; Следният пример демонстрира как може да напишем една функция &#8222;max&#8220; връщаща по-голямото от две числа, като може да й подадем различни типове данни: #include "stdafx.h" #include &#60;iostream&#62; using namespace [...]]]></description>
			<content:encoded><![CDATA[<p>Шаблоните помагат когато искаме да напишем универсална функция, която да може да работи с всякакви типове данни. Синтаксисът е следния:</p>
<pre>	template &lt;class &lt;име-на-класа&gt;&gt;;
	&lt;декларация на функция&gt;</pre>
<p>Следният пример демонстрира как може да напишем една функция &#8222;max&#8220; връщаща по-голямото от две числа, като може да й подадем различни типове данни:<span id="more-298"></span></p>
<pre>	#include "stdafx.h"
	#include &lt;iostream&gt;
	using namespace std;

	template &lt;class T&gt;
	T max (T a, T b) {
		T result = (a&gt;b)?a:b;
		return (result);
	}

	void main (){
		int a=3, b=4;
		int c = max&lt;int&gt;(a,b);
		cout &lt;&lt; "max(" &lt;&lt; a &lt;&lt; ",";
		cout &lt;&lt; b &lt;&lt; ") = " &lt;&lt; c &lt;&lt; endl;

		double d=4.6, e=2.18;
		double f = max&lt;double&gt;(d,e);
		cout &lt;&lt; "max(" &lt;&lt; d &lt;&lt; ",";
		cout &lt;&lt; e &lt;&lt; ") = " &lt;&lt; f &lt;&lt; endl;

		// Може да сравнява и символи по ASCII код
		char g='a', h='z';
		char i = max&lt;char&gt;(g,h);
		cout &lt;&lt; "max(" &lt;&lt; g &lt;&lt; ",";
		cout &lt;&lt; h &lt;&lt; ") = " &lt;&lt; i &lt;&lt; endl;
	}</pre>
<p>* Забележка: В примера типа данни в ъгловите скоби може да се пропусне при извикването на функцията, защото променливите които подаваме са от един и същ тип, както и очакваните входни параметри. Ако предаваме променливи от различен тип, то е задължително да укажем в какъв тип ще преобразуваме.</p>
<p>Възможно е да създадете шаблон, който работи с повече типове:</p>
<pre>	template
	A GetMin (B x, C y) { ... }</pre>
<p>Ето как можем да използваме шаблони върху класове и техните член-функции:</p>
<pre>	#include "stdafx.h"
	#include &lt;iostream&gt;
	using namespace std;

	template &lt;class T&gt;
	class myClass {
		T a, b;
	public:
		myClass(T a, T b){
			this-&gt;a=a;
			this-&gt;b=b;
		}

		T getmax();
	};

	template &lt;class T&gt;
	T myClass&lt;T&gt;::getmax (){
		return ((a&gt;b)?a:b);
	}

	void main () {
		int x = 5;
		int y = 6;
		myClass &lt;int&gt; obj(x, y);
		cout &lt;&lt; obj.getmax() &lt;&lt; endl;

		double a = 8.12;
		int b = 4;
		// Ще преобразуваме данните в double
		myClass &lt;double&gt; obj2(a, b);
		cout &lt;&lt; obj2.getmax() &lt;&lt; endl;
		// А сега ще ги преобразуваме в int
		myClass &lt;int&gt; obj3(a, b);
		cout &lt;&lt; obj3.getmax() &lt;&lt; endl;
	}</pre>
<p>Виждате, че използвайки шаблони ние можем да правим нашите функции и класове много по-универсални.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/298-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd%d0%b8/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Предефиниране на операции</title>
		<link>http://www.cphpvb.net/pik-3/290-%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d1%84%d0%b8%d0%bd%d0%b8%d1%80%d0%b0%d0%bd%d0%b5-%d0%bd%d0%b0-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d0%b8/</link>
		<comments>http://www.cphpvb.net/pik-3/290-%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d1%84%d0%b8%d0%bd%d0%b8%d1%80%d0%b0%d0%bd%d0%b5-%d0%bd%d0%b0-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d0%b8/#comments</comments>
		<pubDate>Sat, 29 Nov 2008 12:33:04 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=290</guid>
		<description><![CDATA[В С++ всяка съществуваща унарна или бинарна операция, в която участва поне един обект от даден клас, може да бъде предефинирана от програмиста. Това дава възможност класовете да бъдат интерпретирани, като нови типове данни, които могат да се използват по начин аналогичен на базовите типове. Предефинирането на операции се осъществява чрез операторни функции. Операторната функция [...]]]></description>
			<content:encoded><![CDATA[<p>В С++ всяка съществуваща унарна или бинарна операция, в която участва поне един обект от даден клас, може да бъде предефинирана от програмиста. Това дава възможност класовете да бъдат интерпретирани, като нови типове данни, които могат да се използват по начин аналогичен на базовите типове. Предефинирането на операции се осъществява чрез операторни функции. Операторната функция е член-функция или приятелска функция на класа, за който тя е дефинирана. Общата форма на една член-функция оператор е следната:</p>
<pre>	&lt;тип-резултат&gt; &lt;име-на-клас&gt;::operator&lt;#&gt;(&lt;аргументи&gt;)
	{
		//изпълнявана операция
	}</pre>
<p>Типът на връщания резултат най-често е същият като типа на класа, за който е дефиниран операторът. Операторът, който се предефинира, замества # в конструкцията. Когато една операторна член-функция предефинира бинарен оператор, функцията ще приема само един параметър. Този параметър ще получава обекта, който е от дясната страна на оператора. Обектът от лявата страна е този, който генерира обръщението към операторната функция и точно той се предавa неявно на функцията посредством указателя this.<span id="more-290"></span></p>
<p>Пример: Следната програма предефинира операторите +, &#8211; и = за клас координатна система:</p>
<pre>	#include "stdafx.h"
	#include &lt;iostream&gt;
	using namespace std;

	class coord {
	private:
		int x, y;
	public:
		coord(){
			x=0;
			y=0;
		}
		coord(int x, int y){
			this-&gt;x=x;
			this-&gt;y=y;
		}
		int get_x(){
			return (this-&gt;x);
		}
		int get_y(){
			return (this-&gt;y);
		}
		void show(){
			cout &lt;&lt; "x = " &lt;&lt; get_x() &lt;&lt; endl;
			cout &lt;&lt; "y = " &lt;&lt; get_y() &lt;&lt; endl;
		}
		// Бинарни оператори + и -
		coord operator+(coord &amp;);
		coord operator-(coord &amp;);
		// Оператор за присвояване
		coord operator=(coord);
		// Унарни оператори
		coord operator++(); // Префиксен
		coord operator++(int); // Постфиксен
		coord operator--(); // Префиксен
		coord operator--(int); // Постфиксен
	};

	coord coord::operator+(coord &amp;obj){
		coord temp;

		temp.x = this-&gt;x+obj.x;
		temp.y = this-&gt;y+obj.y;

		return temp;
	}

	coord coord::operator-(coord &amp;obj){
		coord temp;

		temp.x = this-&gt;x-obj.x;
		temp.y = this-&gt;y-obj.y;

		return temp;
	}

	coord coord::operator=(coord obj){
		this-&gt;x = obj.x;
		this-&gt;y = obj.y;

		return *this;
	}
	coord coord::operator++(){
		this-&gt;x++;
		this-&gt;y++;
		return *this;
	}

	coord coord::operator++(int i){
		this-&gt;x++;
		this-&gt;y++;
		return *this;
	}

	coord coord::operator--(){
		this-&gt;x--;
		this-&gt;y--;
		return *this;
	}

	coord coord::operator--(int i){
		this-&gt;x--;
		this-&gt;y--;
		return *this;
	}

	int main(){
		coord o1(5,5), o2(2,-2), o3;
		cout &lt;&lt; "O1: " &lt;&lt; endl;
		o1.show();
		cout &lt;&lt; endl;
		cout &lt;&lt; "O2: " &lt;&lt; endl;
		o2.show();
		cout &lt;&lt; endl;

		cout &lt;&lt; "o3 = o1 + o2 =&gt;" &lt;&lt; endl;
		o3 = o1 + o2;
		o3.show();
		cout &lt;&lt; endl;

		cout &lt;&lt; "o3 = o1 - o2 =&gt;" &lt;&lt; endl;
		o3 = o1 - o2;
		o3.show();
		cout &lt;&lt; endl;

		cout &lt;&lt; "o3 = o1 =&gt;" &lt;&lt; endl;
		o3 = o1;
		o3.show();
		cout &lt;&lt; endl;

		o3++;
		cout &lt;&lt; "o3++ =&gt;" &lt;&lt; endl;
		o3.show();
		cout &lt;&lt; endl;

		++o3;
		cout &lt;&lt; "++o3 =&gt;" &lt;&lt; endl;
		o3.show();
		cout &lt;&lt; endl;

		o3--;
		cout &lt;&lt; "o3-- =&gt;" &lt;&lt; endl;
		o3.show();
		cout &lt;&lt; endl;

		--o3;
		cout &lt;&lt; "--o3 =&gt;" &lt;&lt; endl;
		o3.show();
		cout &lt;&lt; endl;
		return 0;
	}</pre>
<p>Операторната функция operator=() връща *this, т.е. тя връща обекта, на който се присвоява стойност. Връщайки като резултат *this, предефинираният оператор за присвояване позволява на обектите да бъдат използвани в поредица от присвоявания. Например:</p>
<pre>		о3 = о2 = о1;</pre>
<p>При предефиниране на операциите + и &#8211; използвахме псевдоними да предаване на стойността. В други случаи може да се наложи да ги предавате по стойност (както направихме с оператора =).</p>
<p>При унарните оператори ако оператора се намира пред операнда (напр. ++o3), то се извиква функцията operator#(). Ако оператора е след операнда (напр. o3++), то се извиква функцията operator#(int i). В този случай на &#8222;i&#8220; винаги ще се предава стойност 0.</p>
<p><strong>Задача</strong>: Препишете горният пример, така че функциите бинарните и унарните оператори да са приятелски функции.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/290-%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d1%84%d0%b8%d0%bd%d0%b8%d1%80%d0%b0%d0%bd%d0%b5-%d0%bd%d0%b0-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%86%d0%b8%d0%b8/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Namespace конструкции и нов стил header файлове</title>
		<link>http://www.cphpvb.net/pik-3/484-namespace-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8-%d0%b8-%d0%bd%d0%be%d0%b2-%d1%81%d1%82%d0%b8%d0%bb-header-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d0%b5/</link>
		<comments>http://www.cphpvb.net/pik-3/484-namespace-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8-%d0%b8-%d0%bd%d0%be%d0%b2-%d1%81%d1%82%d0%b8%d0%bb-header-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d0%b5/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 07:31:49 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=484</guid>
		<description><![CDATA[Namespace е конструкция за езика C++, която представлява разширение на познатите досега класове, а именно &#8211; един namespace може да съдържа в себе си набори от класове. По този начин от една страна се получава естествено обединение на обектите, които имат сходна функционалност, а от друга се решава един основен проблем в дизайна на програмите. [...]]]></description>
			<content:encoded><![CDATA[<p>Namespace е конструкция за езика C++, която представлява разширение на познатите досега класове, а именно &#8211; един namespace може да съдържа в себе си набори от класове. По този начин от една страна се получава естествено обединение на обектите, които имат сходна функционалност, а от друга се решава един основен проблем в дизайна на програмите. Представете си, че имате два header файла, които искате да използвате:</p>
<pre>	#include "header1.h"
	#include "header2.h"</pre>
<p>Нека обаче в тези файлове се съдържат класове с повтарящи се имена:<span id="more-484"></span></p>
<pre>	// header1.h
	class myClass {
		...
	};
	...

	// header2.h
	class myClass {
		...
	};
	...</pre>
<p>В такъв случай моментално в нашата програма ще се получи конфликт, понеже ще се опитаме да дефинираме myClass два пъти. Този проблем се решава, като използваме namespace конструкцията:</p>
<pre>	// header1.h
	namespace header1 {
		class myClass {
			...
		};
	}

	// header2.h
	namespace header2 {
		class myClass {
			...
		};
	}</pre>
<p>Когато искаме да използваме така създадените header файлове ние имаме два метода за работа с класовете в тях. Първият начин е да се извикват директно, чрез указване на namespace:</p>
<pre>	main(){
		...
		header1::myClass a;
		header2::myClass *d = new header1::myClass;
		...
	}</pre>
<p>Друг начин е да използваме ключовата дума “using” за един от класовете:</p>
<pre>	main(){
		...
		using namespace header1;
		myClass a; // a ще е от класа в header1
		header2::myClass *d = new header2::myClass;
		...
	}</pre>
<p>Имайте в предвид, че ако укажете “using namespace header1″ и “using namespace header2″ отново ще се появи споменатият преди това конфликт. Затова при използване на namespace се препоръчва да се използва операторът “::”. Ако дефинирате namespace, който няма име, то той по подразбиране ще бъде включен чрез ключовата дума “using” от компилаторът.</p>
<p>Интересна и често използвана при писане на библиотеки възможност са вложени namespace:</p>
<pre>	namespace root
	{
		class A{
		public:
			int var1;
		};

		namespace sub
		{
  			class A{
			public:
				int var2;
			};
		}
	}

	int main () {
		root::A a;
		a.var1 = 5;

		root::sub::A b;
		b.var2 = 6;

		return 0;
	}</pre>
<p>Най-често използвания и най-популярен namespace е “std”. Принципно “C++ Standards Committee” са пренаписали напълно стандартната библиотека на C++, като са сложили най-често използваните стандартизирани обекти в този namespace.</p>
<p>Друго много важно обновяване на езика е въвеждането на нов стил header файлове. Досега не сме ги разглеждали, понеже целяхме да имаме максимална съвместимост за програми писани на С и стари компилатори. В кода на програмата всъщност няма особена разлика &#8211; просто не се добавя “.h” в името на файла при include:</p>
<pre>	Стар стил:
	#include "iostream.h"
	#include "fstream.h"
	#include "string.h"
	#include "math.h"
	#include "stdlib.h"

	Нов стил:
	#include &lt;iostream&gt;
	#include &lt;fstream&gt;
	#include &lt;string&gt;
	#include &lt;math&gt;
	#include &lt;cstdlib&gt;</pre>
<p>Въпреки, че имат известни разлики в имплементацията (например fstream.h добавя iostream.h автоматично, а fstream не; string.h използва С-стил низове, а string използва обектни низове; r тн) главната функционалност и най-често използваните функции остават същите. Препоръчително е при писането на програми за нови компилатори да използвате новата конвенция. Нещата, които трябва да запомните са:<br />
1. Никога не “миксирайте”, като вкарвате библиотеки от стар и нов стил едновременно.<br />
2. Ако компилаторът поддържа новите библиотеки, то е добре да използвате тях, тъй като се счита, че функционалността и надеждността при тях е подобрена.<br />
3. Не е изключено в близко бъдеще новите компилатори да не поддържат старите библиотеки.<br />
4. Ако искате да използвате namespace std, то трябва да добавите поне една от новите библиотеки.</p>
<p>По принцип всички функции в новите стандартни библиотеки използват namespace std. Следният пример демонстрира това, като в допълнение показва още една новост за миксиране на глобални и локални променливи с едно и също име:</p>
<pre>	#include "stdafx.h"
	#include
	// Глобална променлива
	int var = 5;

	void main(){
		// Локална променлива
		int var = 10;
		// Отпечатваме локалната променлива
		std::cout &lt;&lt; var &lt;&lt; std::endl;
		// Отпечатваме глобалната променлива
		std::cout &lt;&lt; ::var &lt;&lt; std::endl;
		// Добавяме namespace std
		using namespace std;
		// Вече може да използваме cout директно
		cout &lt;&lt; "Hello world" &lt;&lt; endl;
	}</pre>
<p>Забележете, че ако не сме добавили “using namespace std” при новия стил функции, то програмата няма да разпознае функциите ако не ги извикаме чрез “std::”.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/484-namespace-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8-%d0%b8-%d0%bd%d0%be%d0%b2-%d1%81%d1%82%d0%b8%d0%bb-header-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d0%b5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Виртуални функции</title>
		<link>http://www.cphpvb.net/pik-3/282-%d0%b2%d0%b8%d1%80%d1%82%d1%83%d0%b0%d0%bb%d0%bd%d0%b8-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/</link>
		<comments>http://www.cphpvb.net/pik-3/282-%d0%b2%d0%b8%d1%80%d1%82%d1%83%d0%b0%d0%bb%d0%bd%d0%b8-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 16:59:25 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=282</guid>
		<description><![CDATA[Виртуалната функция e член-функция, която се дефинира в базовия клас и се предефинира в производния клас. Както и при виртуалните класове ключовата дума е virtual. Когато виртуална функция се предефинира в производен клас, ключовата дума virtual не е необходима. Чрез виртуалните функции се постига също &#8222;полиморфизъм по време на изпълнение&#8220;. За целта виртуалната функция трябва [...]]]></description>
			<content:encoded><![CDATA[<p>Виртуалната функция e член-функция, която се дефинира в базовия клас и се предефинира в производния клас. Както и при виртуалните класове ключовата дума е virtual. Когато виртуална функция се предефинира в производен клас, ключовата дума virtual не е необходима. Чрез виртуалните функции се постига също &#8222;полиморфизъм по време на изпълнение&#8220;. За целта виртуалната функция трябва да бъде извикана посредством указател. Когато указател към базов клас сочи към обект от производен клас, съдържащ виртуална функция, и тази функция се извика посредством указател, С++ решава коя версия на функцията ще бъде извикана въз основа на типа на обекта, сочен от указателя. Именно това решение се взема по време на изпълнение.<span id="more-282"></span></p>
<p>Пример: Следната програма създава общ базов клас, наречен area, който съдържа двата размера на една фигура. Той също така декларира чисто виртуална функция getarea(), която е предефинирана от производните класове, и връща лицето на типа фигура, дефинирана от производния клас.</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	class area {
		double dim1, dim2;
		public:
		void setarea(double d1, double d2)
		{
			dim1 = d1;
			dim2 = d2;
		}
		void getdim(double &amp;d1, double &amp;d2)
		{
			d1 = dim1;
			d2 = dim2;
		}
		virtual double getarea() = 0;
	};

	class rectangle : public area {
		public:
		double getarea()
		{
			double a, b;
			getdim(a, b);
			return a*b;
		}
	};

	class triangle : public area {
		public:
		double getarea()
		{
			double a, ha;
			getdim(a, ha);
			return (a*ha)/2;
		}
	};

	int main()
	{
		rectangle r;
		int a, b;
		cout &lt;&lt; "Vavedete daljinata na stranata a: ";
		cin &gt;&gt; a;
		cout &lt;&lt; "Vavedete daljinata na stranata b: ";
		cin &gt;&gt; b;
		r.setarea(a, b);

		triangle t;
		cout &lt;&lt; "Vavedete stranata AB na triagalnik: ";
		cin &gt;&gt; a;
		cout &lt;&lt; "Vavedete visochinata kam tazi strana: ";
		cin &gt;&gt; b;
		t.setarea(a, b);

		area *p;

		p = &amp;r;
		cout &lt;&lt; "Pravoagalnikat ima lice: ";
		// Извикваме виртуалната функция от клас area
		cout &lt;&lt; p-&gt;getarea() &lt;&lt; endl;

		p = &amp;t;
		cout &lt;&lt; "Liceto na triagalnika e: ";
		// Отново извикваме виртуалната функция от клас area
		// но тя вече сочи съм getarea() от triangle
		cout &lt;&lt; p-&gt;getarea();
		cout &lt;&lt; endl;
		return 0;
	}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/282-%d0%b2%d0%b8%d1%80%d1%82%d1%83%d0%b0%d0%bb%d0%bd%d0%b8-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Виртуални класове</title>
		<link>http://www.cphpvb.net/pik-3/253-%d0%b2%d0%b8%d1%80%d1%82%d1%83%d0%b0%d0%bb%d0%bd%d0%b8-%d0%ba%d0%bb%d0%b0%d1%81%d0%be%d0%b2%d0%b5/</link>
		<comments>http://www.cphpvb.net/pik-3/253-%d0%b2%d0%b8%d1%80%d1%82%d1%83%d0%b0%d0%bb%d0%bd%d0%b8-%d0%ba%d0%bb%d0%b0%d1%81%d0%be%d0%b2%d0%b5/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 16:59:20 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=253</guid>
		<description><![CDATA[При директното наследяване на множество базови класове е възможно един производен клас да наследи многократно даден базов клас. Така обаче може да се получи дублиране на член променливи. Нека например класа vehicle има два производни класа: motorvehicle (добавя допълнителна информация за типа двигател на превозното срество) и passengervehicle (добавя информация за максималния брой пътници в [...]]]></description>
			<content:encoded><![CDATA[<p>При директното наследяване на множество базови класове е възможно един производен клас да наследи многократно даден базов клас. Така обаче може да се получи дублиране на член променливи.</p>
<p>Нека например класа vehicle има два производни класа: motorvehicle (добавя допълнителна информация за типа двигател на превозното срество) и passengervehicle (добавя информация за максималния брой пътници в превозното средство). Ако създадем клас car, който наследява едновременно motorvehicle и passengervehicle, то ние ще получим дублиране на член-променливи, тъй като класа car ще наследи двукратно член-променливите декларирани в класа vehicle.</p>
<p>Многократното наследяване може да се избегне чрез наследяване на базовия клас като виртуален. Това предотвратява присъствието на 2(или повече) копия на базовия клас във всеки следващ индиректен производен клас. Декларацията в този случай ще има вида:<span id="more-253"></span></p>
<pre>	class vehicle { ... };
	class motorvehicle : virtual public vehicle { ... };
	class passengervehicle : virtual public vehicle { ... };
	class car : public motorized, public road_use { ... };</pre>
<p>Ето как ще изглежда примерната програма:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	class vehicle {
		int num_wheels;
		int weight;
		public:
		vehicle(int w, int r)
		{
			num_wheels = w; weight = r;
		}
		void showv(){
			cout &lt;&lt; "Wheels:" &lt;&lt; num_wheels &lt;&lt; endl;
			cout &lt;&lt; "Weight:" &lt;&lt; weight &lt;&lt; endl;
		}
	};

	enum motor {gas, electric, diesel};

	class motorvehicle : virtual public vehicle {
		enum motor mtr;
		public:
		motorvehicle(enum motor m, int w, int r) : vehicle(w, r) {
			mtr = m;
		}

		void showm() {
			cout &lt;&lt; "Motor: ";
			switch(mtr) {
				case gas : cout &lt;&lt; "Gas";
					break;
				case electric : cout &lt;&lt; "Electric";
					break;
				case diesel : cout &lt;&lt; "Diesel";
					break;
			}
			cout &lt;&lt; endl;
		}
	};

	class passangervehicle : virtual public vehicle {
		int passengers;
		public:
		passangervehicle(int p, int w, int r) : vehicle(w, r){
			passengers = p;
		}

		void showp() {
			cout &lt;&lt; "Passengers:" &lt;&lt; passengers &lt;&lt; '\n';
		}
	};

	enum steering {power, rack_pinion, manual};

	class car : public motorvehicle, public passangervehicle {
		enum steering strng;
		public:
		car(enum steering s, enum motor m, int p, int w, int r) :
			motorvehicle(m, w, r), passangervehicle(p, w, r), vehicle(w, r)
		{
			strng = s;
		}

		void show() {
			showv();
			showp();
			showm();
			cout &lt;&lt; "Steering: ";
			switch(strng) {
				case power : cout &lt;&lt; "Power";
					break;
				case rack_pinion : cout &lt;&lt; "Rack and pinion";
					break;
				case manual : cout &lt;&lt; "Manual";
					break;
			}
			cout &lt;&lt; endl;
		}
	};

	int main() {
		car c(power, gas, 5, 4, 1200);
		c.show();
		return 0;
	}</pre>
<p><strong>Задача</strong>: Към горният пример добавете клас &#8222;truck&#8220;, който е производен само на класа &#8222;motorvehicle&#8220; и добавя като функционалност член променлива load (максимален товар) и функция, която го отпечатва на екрана.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/253-%d0%b2%d0%b8%d1%80%d1%82%d1%83%d0%b0%d0%bb%d0%bd%d0%b8-%d0%ba%d0%bb%d0%b0%d1%81%d0%be%d0%b2%d0%b5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Указател към функция</title>
		<link>http://www.cphpvb.net/pik-3/284-%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb-%d0%ba%d1%8a%d0%bc-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f/</link>
		<comments>http://www.cphpvb.net/pik-3/284-%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb-%d0%ba%d1%8a%d0%bc-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 16:59:15 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=284</guid>
		<description><![CDATA[Указателите към функции водят до някои много интересни и ефективни програмни техники. Както подсказва името им &#8211; това са указатели, които сочат към адреса в паметта, където е записана дадена функция. Тук трябва да отбележим, че указателите към функции не са нововъведение от С++, а са известни още от много компилатори за С. Оказват се [...]]]></description>
			<content:encoded><![CDATA[<p>Указателите към функции водят до някои много интересни и ефективни програмни техники. Както подсказва името им &#8211; това са указатели, които сочат към адреса в паметта, където е записана дадена функция. Тук трябва да отбележим, че указателите към функции не са нововъведение от С++, а са известни още от много компилатори за С. Оказват се особено подходящи при извикване на &#8222;callbacks&#8220; и за създаване на събития (events). Callback наричаме функция, която програмистът не е извикал изрично в програмния код. За тяхното изпълнение се грижи друга функция, която е приела указател към нейния адрес.<span id="more-284"></span></p>
<p>Дефиницирнето на указатели към фунции се получава по следният начин:</p>
<pre>	&lt;тип връщан резултат&gt; (*&lt;име&gt;) (&lt;входни параметри&gt;);</pre>
<p>Пример: Дефинираме две функции max и min, които предаваме чрез указател на друга функция show, която ги изпълнява:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	void max(int a, int b){
		cout &lt;&lt; "the bigger number is: ";
		cout &lt;&lt; ((a&gt;b)?a:b);
		cout &lt;&lt; endl;
	}

	void min(int a, int b){
		cout &lt;&lt; "the lower number is: ";
		cout &lt;&lt; ((a&lt;b)?a:b);
		cout &lt;&lt; endl;
	}

	// show приема като трети параметър указател към
	// функция, която е от тип void и е с входни параметри
	// две числа от тип int
	void show(int x, int y, void(*pFunc)(int, int)){
		pFunc(x, y);
	}

	void main()
	{
		// Създаваме указател
		void(*ptr2func)(int, int);
		// Насочваме указателя към функцията max
		ptr2func = max;
		show(2 , 3 , ptr2func);
		// Сега насочваме указателя към min
		ptr2func = min;
		show(2 , 3 , ptr2func);
	}</pre>
<p>От примера веднага става ясно, че синтаксисът не е много удобен за работа. Тук на помощ идва typedef, чрез който можем да зададем ново име на типа. Указателя от горният пример може да бъде създаден като тип по следния начин:</p>
<pre>	typedef void(*COMPARE)(int, int);
	// Сега можем да създаваме обекти от тип COMPARE
	COMPARE ptr2func;</pre>
<p><strong>Задача</strong>: Създайте функции plus, minus, multiply и divide, които приемат две числа от тип double и връщат като резултат съответно тяхния сбор, разлика, умножение и деление. Създайте указатели към тези функции и ги изпратете последователно като параметър на функция show, която отпечатва резултатът.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/284-%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb-%d0%ba%d1%8a%d0%bc-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Наследяване</title>
		<link>http://www.cphpvb.net/pik-3/251-%d0%bd%d0%b0%d1%81%d0%bb%d0%b5%d0%b4%d1%8f%d0%b2%d0%b0%d0%bd%d0%b5/</link>
		<comments>http://www.cphpvb.net/pik-3/251-%d0%bd%d0%b0%d1%81%d0%bb%d0%b5%d0%b4%d1%8f%d0%b2%d0%b0%d0%bd%d0%b5/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 16:59:04 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=251</guid>
		<description><![CDATA[Когато един клас наследява друг се използва общата форма: class &#60;производен-клас&#62;:&#60;тип-достъп&#62; &#60;име-базов-клас&#62; { //... }; Типът достъп е една от трите ключови думи: public, private или protected. Разликата между тях е: - Ако наследяването е тип public, то на производния клас се допуска достъп до членовете на неговия собствен клас, на неговия базов клас и [...]]]></description>
			<content:encoded><![CDATA[<p>Когато един клас наследява друг се използва общата форма:</p>
<pre>	class &lt;производен-клас&gt;:&lt;тип-достъп&gt; &lt;име-базов-клас&gt; {
		//...
	};</pre>
<p>Типът достъп е една от трите ключови думи: public, private или protected. Разликата между тях е:<br />
- Ако наследяването е тип public, то на производния клас се допуска достъп до членовете на неговия собствен клас, на неговия базов клас и на функции, външни за класовете.<br />
- Ако наследяването е тип protected, то се допуска достъп до членовете на неговия собствен клас, на неговия базов клас, но не се допуска достъп на функции външни за класа.<br />
- Ако наследяването е тип private, то производният клас няма достъп до private елементите на базовия клас и външни функции.<span id="more-251"></span></p>
<p>Ако е необходимо да се предаде аргумент на конструктора на базовия клас, то всички необходими аргументи за базовия и за производния клас се предават на конструктора на производния клас. Като се използва разширената форма на декларация на конструктора на производния клас, могат да се предадат съответните аргументи и към базовия клас:</p>
<pre>	&lt;производен конструктор&gt;(списък аргументи):&lt;базов-клас&gt;(списък аргументи) {
		//тяло на конструктора на производния клас
	}</pre>
<p><strong>Пример</strong>: Дефинираме базов клас vehicle и два производни класа &#8211; car и truck:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	// Базов клас превозно средство
	class vehicle {
		int num_wheels;
		int weight;

		public:
		// Конструктор
		vehicle(int w, int r)
		{
			num_wheels = w;
			weight = r;
		}
		// Функция, която отпечатва броя гуми
		// и тежестта на превозното средство
		void showv(){
			cout &lt;&lt; "Wheels: ";
			cout &lt;&lt; num_wheels;
			cout &lt;&lt; endl;
			cout &lt;&lt; "Weight: ";
			cout &lt;&lt; weight;
			cout &lt;&lt; endl;
		}
	};

	// Клас кола наследява клас превозно средство
	class car : public vehicle {
		// Добавя се нова променлива
		int passengers;

		public:
		// Конструктора се предефинира, така че
		// да приема три аргумента. Два от тях се
		// предават като аргументи на конструктора
		// на базовия клас
		car(int p, int w, int r) : vehicle(w, r)
		{
			passengers = p;
		}

		// В нова функция show извикваме вече
		// съществуващата в базовия клас функция
		// showv и добавяме функционалност
		void show()
		{
			showv();
			cout &lt;&lt; "Passengers: ";
			cout &lt;&lt; passengers;
			cout &lt;&lt; endl;
		}
	};

	// Аналогично създаваме втори производен клас
	class truck : public vehicle {
		int loadlimit;

		public:

		truck(int l, int w, int r) : vehicle(w, r)
		{
			loadlimit = l;
		}

		void show(){
			showv();
			cout &lt;&lt; "Loadlimit: ";
			cout &lt;&lt; loadlimit;
			cout &lt;&lt; endl;
		}
	};

	int main()
	{
		car c(5, 4, 1200);
		truck t(30000, 12, 3000);
		cout &lt;&lt; "Car: " &lt;&lt; endl;
		c.show();
		cout &lt;&lt; endl &lt;&lt; "Truck " &lt;&lt; endl;
	 	t.show();
		return 0;
	}</pre>
<p><strong>Задача</strong>: Съставете базов клас триъгълник с четири елемента дължина на съответните страни и конструктори, който инициализират и валидират входните данни. Направете функция на базовия клас за намиране на лицето на триъгълника по хереоновата хормула. Създайте:<br />
- Производен клас &#8222;равнобедрен триъгълник&#8220; и предефинирайте конструктора.<br />
- Производен клас &#8222;равностранен триъгълник&#8220; и предефинирайте конструктора. Напишете втора функция за изчисляване на лицето на триъгълник, която използва директно формулата за лице на равностранен триъгълник: a*a*sqrt(3)/4.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/251-%d0%bd%d0%b0%d1%81%d0%bb%d0%b5%d0%b4%d1%8f%d0%b2%d0%b0%d0%bd%d0%b5/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Допълнителни задачи към упражнение 4</title>
		<link>http://www.cphpvb.net/pik-3/234-%d0%b4%d0%be%d0%bf%d1%8a%d0%bb%d0%bd%d0%b8%d1%82%d0%b5%d0%bb%d0%bd%d0%b8-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8-%d0%ba%d1%8a%d0%bc-%d1%83%d0%bf%d1%80%d0%b0%d0%b6%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-4/</link>
		<comments>http://www.cphpvb.net/pik-3/234-%d0%b4%d0%be%d0%bf%d1%8a%d0%bb%d0%bd%d0%b8%d1%82%d0%b5%d0%bb%d0%bd%d0%b8-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8-%d0%ba%d1%8a%d0%bc-%d1%83%d0%bf%d1%80%d0%b0%d0%b6%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-4/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 16:58:42 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=234</guid>
		<description><![CDATA[Задача: Дефинирайте клас point с елементи координатите на точка x и y. - Дефинирайте член-функция show, която отпечатва координатите на точката. - Дефинирайте член-функция dist, която приема два псевдонима към клас point и връща разстоянието между подадените две точки. - Предефинирайте член-функцията dist, така че да и предаваме указатели към две точки. Задача: Дефинирайте два [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Задача</strong>: Дефинирайте клас <strong>point </strong>с елементи координатите на точка <strong>x </strong>и <strong>y</strong>.<br />
- Дефинирайте член-функция <strong>show</strong>, която отпечатва координатите на точката.<br />
- Дефинирайте член-функция <strong>dist</strong>, която приема два псевдонима към клас point и връща разстоянието между подадените две точки.<br />
- Предефинирайте член-функцията <strong>dist</strong>, така че да и предаваме указатели към две точки.</p>
<p><strong>Задача</strong>: Дефинирайте два класа &#8211; програмист и мениджър. Всеки от класовете да съдържа public елементи име, години и трудов стаж. Като private елементи двата класа да имат елементи заплата и масив от 12 елемента от тип int, в който да се записват броя работни часове за месеците през годината. Напишете:<br />
- Конструктори и деструктори на класовете.<br />
- Приятелска функция за двата класа, която показва кой повече е работил през годината и съответно кой взима по-голяма заплата.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/234-%d0%b4%d0%be%d0%bf%d1%8a%d0%bb%d0%bd%d0%b8%d1%82%d0%b5%d0%bb%d0%bd%d0%b8-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8-%d0%ba%d1%8a%d0%bc-%d1%83%d0%bf%d1%80%d0%b0%d0%b6%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stack или heap?</title>
		<link>http://www.cphpvb.net/pik-3/248-stack-%d0%b8%d0%bb%d0%b8-heap/</link>
		<comments>http://www.cphpvb.net/pik-3/248-stack-%d0%b8%d0%bb%d0%b8-heap/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 08:03:27 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=248</guid>
		<description><![CDATA[При разглеждането на оператора new споменахме понятието &#8222;динамична памет&#8220; (heap), но не дадохме ясно определение защо се използва. Когато дефинираме променливи по обикновения познат начин (например &#8222;int x = 5;&#8220;) те се записват в стека (stack) на паметта. Стандартно тази памет е 1MB и може да се досетите, че в много случаи тя ще бъде [...]]]></description>
			<content:encoded><![CDATA[<p>При разглеждането на оператора new споменахме понятието &#8222;динамична памет&#8220; (heap), но не дадохме ясно определение защо се използва. Когато дефинираме променливи по обикновения познат начин (например &#8222;int x = 5;&#8220;) те се записват в стека (stack) на паметта. Стандартно тази памет е 1MB и може да се досетите, че в много случаи тя ще бъде недостатъчна (например ако искаме да създадем гигантски масив с един милион елемента double d[1000000]). Компилаторът няма да даде грешка, но програмата няма да може да се изпълни (ще се даде грешка от типа stack overflow).<span id="more-248"></span></p>
<p>За да се справите с този проблем трябва да дефинирате такива големи масиви/обекти в динамичната памет:</p>
<pre>	double *d = new double[1000000];</pre>
<p>Операторът new записва обектите в динамичната памет, която е с обем почти цялата RAM памет на компютъра. В допълнение ако дори тази RAM не е достатъчна, то операционната система ще ви позволи да пишете и на хард диска в swap file/partition. За да работите с масива от примера например ще се наложи да си припомните урока за адресна аритметика. Единствения недостатък в случая, е че трябва да се грижим явно да &#8222;унищожаваме&#8220; елементите чрез оператора delete.</p>
<p><strong>Задача</strong>: Създайте масив от 1 милион елемента от тип long и го запълнете с числата от едно до един милион. След това запишете съдържанието на масива във файл, като използвате интервал като разделител за числата. Добавете нов ред след всяко десето число.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/248-stack-%d0%b8%d0%bb%d0%b8-heap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Приятелски функции</title>
		<link>http://www.cphpvb.net/pik-3/232-%d0%bf%d1%80%d0%b8%d1%8f%d1%82%d0%b5%d0%bb%d1%81%d0%ba%d0%b8-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/</link>
		<comments>http://www.cphpvb.net/pik-3/232-%d0%bf%d1%80%d0%b8%d1%8f%d1%82%d0%b5%d0%bb%d1%81%d0%ba%d0%b8-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 08:02:55 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=232</guid>
		<description><![CDATA[Приятелски се наричат функциите, които не са член-функции на клас, но имат достъп до неговите private елементи. Приятелски функции се използват, когато е необходимо една функция да има достъп до private членовете на два или повече различни класа. Декларацията на приятелската функция може да се намира както в частта public, така и в частта private и се характеризира [...]]]></description>
			<content:encoded><![CDATA[<p>Приятелски се наричат функциите, които не са член-функции на клас, но имат достъп до неговите private елементи. Приятелски функции се използват, когато е необходимо една функция да има достъп до private членовете на два или повече различни класа. Декларацията на приятелската функция може да се намира както в частта public, така и в частта private и се характеризира с ключовата дума friend, която се поставя в началото на декларацията. Една приятелска функция се дефинира като обикновена функция, която не е член на клас. Има два вида приятелски функции:<span id="more-232"></span></p>
<p>1. Независима приятелска функция: Тези функции се декларират във всеки от класовете като приятелски. Те не са член-функции на класа и затова те нямат достъп до елементите му. Поради тази причина е необходимо подаването на обект по явен начин като параметър на функцията (съответно извикването ще се извършва чрез името на функцията и списък от фактически параметри).</p>
<p>Пример: Дефинираме два класа представляващи марки автомобили с обща функция за определяне на по-бързият автомобил:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	// Предварителна декларация
	class bmw;
	class porsche;

	class bmw{
	private:
		unsigned maxspeed;
	public:
		// Приятелска функция
		friend int cmpspeed(bmw *, porsche *);

		bmw(char *, unsigned speed);
		char *model;
	};

	bmw::bmw(char *c, unsigned speed){
		model = c;
		maxspeed = speed;
	}

	class porsche{
	private:
		unsigned maxspeed;
	public:
		friend int cmpspeed(bmw *, porsche*);
		porsche(char *, unsigned speed);
		char *model;
	};

	porsche::porsche(char *c, unsigned speed){
		model = c;
		maxspeed = speed;
	}

	// Дефиниция на приятелската функция
	int cmpspeed(bmw *a, porsche *b){
		// Тя има достъп от елементите maxspeed
		// въпреки че те са private!
		return (a-&gt;maxspeed - b-&gt;maxspeed);
	}

	void main(){
		bmw *x6 = new bmw("X6 xDrive 35i", 239);
		porsche *cayenne = new porsche("Cayenne S", 270);
		if (cmpspeed(x6, cayenne) &lt; 0){
			cout &lt;&lt; cayenne-&gt;model;
			cout &lt;&lt; " is faster!" &lt;&lt; endl;
		}
		else{
			if (cmpspeed(x6, cayenne) &gt; 0){
				cout &lt;&lt; x6-&gt;model;
				cout &lt;&lt; " is faster!" &lt;&lt; endl;
			}
			else{
				cout &lt;&lt; x6-&gt;model;
				cout &lt;&lt; " and ";
				cout &lt;&lt; cayenne-&gt;model;
				cout &lt;&lt; " are at equal speeds";
			}
		}
	}</pre>
<p>2.  Член-функция на клас като приятелска за друг клас: При декларирането на приятелската функция трябва да се прецизира класът, на който тя е член-функция с помощта на оператор за принадлежност (::).</p>
<p>Пример: Отново условието от горният пример, но този път функцията cmpspeed е член-функция на класа bmw. Промените в кода са удебелени:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	class porsche;

	class bmw{
	private:
		unsigned maxspeed;
	public:
		bmw(char *, unsigned speed);
		char *model;
		// За BMW вече cmpspeed е член-функция
		<em><strong>int cmpspeed(porsche *);</strong></em>
	};

	class porsche{
	private:
		unsigned maxspeed;
	public:
		// Извикваме функцията като приятелска
		<em><strong>friend int bmw::cmpspeed(porsche*);</strong></em>
		porsche(char *, unsigned speed);
		char *model;
	};

	bmw::bmw(char *c, unsigned speed){
		model = c;
		maxspeed = speed;
	}

	// Дефиниция на самата функция
<em><strong>	int bmw::cmpspeed(porsche *b){
		return (maxspeed - b->maxspeed);
	}</strong></em>

	porsche::porsche(char *c, unsigned speed){
		model = c;
		maxspeed = speed;
	}

	void main(){
		bmw *x6 = new bmw("X6 xDrive 35i", 239);
		porsche *cayenne = new porsche("Cayenne S", 270);
		if (<em><strong>x6->cmpspeed(cayenne) < 0</strong></em>){
			cout << cayenne->model;
			cout << " is faster!" << endl;
		}
		else{
			if (<em><strong>x6->cmpspeed(cayenne) > 0</strong></em>){
				cout << x6->model;
				cout << " is faster!" << endl;
			}
			else{
				cout << x6->model;
				cout << " and ";
				cout << cayenne->model;
				cout << " are at equal speeds";
			}
		}
	}
</pre>
<p><strong>Задача</strong>: Дефинирайте класове успоредник, квадрат и правоъгълник и напишете член-функции за изчисляване на лицата и периметрите на фигурите. Напишете:<br />
- Приятелска за трите класа функция, която отпечатва на екрана фигурата с най-голямо лице и самото лице.<br />
- Член-функция на класа успоредник, която е приятелска за другите два класа и връща числата 0, 1 или 2 в зависимост от това коя от фигурите е с най-голям периметър.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/232-%d0%bf%d1%80%d0%b8%d1%8f%d1%82%d0%b5%d0%bb%d1%81%d0%ba%d0%b8-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Класове, член-функции, конструктори и деструктори</title>
		<link>http://www.cphpvb.net/pik-3/226-%d0%ba%d0%bb%d0%b0%d1%81%d0%be%d0%b2%d0%b5-%d1%87%d0%bb%d0%b5%d0%bd-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d0%be%d1%80%d0%b8-%d0%b8-%d0%b4/</link>
		<comments>http://www.cphpvb.net/pik-3/226-%d0%ba%d0%bb%d0%b0%d1%81%d0%be%d0%b2%d0%b5-%d1%87%d0%bb%d0%b5%d0%bd-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d0%be%d1%80%d0%b8-%d0%b8-%d0%b4/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 08:02:33 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=226</guid>
		<description><![CDATA[Класовете позволяват да дефинираме нови типове данни. Един клас представлява описание на тип, включващ едновременно данни и функции, които ги обработват. Данните се наричат член-променливи, а функциите – член-функции. Дефиницията на един клас включва декларация на класа и дефиниции на член-функциите. Декларацията на класа има следния синтаксис: class &#60;име-на-клас&#62;{ // Декларации на член-променливи // Декларации [...]]]></description>
			<content:encoded><![CDATA[<p>Класовете позволяват да дефинираме нови типове данни. Един клас представлява описание на тип, включващ едновременно данни и функции, които ги обработват. Данните се наричат член-променливи, а функциите – член-функции. Дефиницията на един клас включва декларация на класа и дефиниции на член-функциите.</p>
<p>Декларацията на класа има следния синтаксис:</p>
<pre>	class  &lt;име-на-клас&gt;{
		// Декларации на член-променливи
		// Декларации на член-функции
	};</pre>
<p>Дефиницията на член-функция има следния синтаксис:</p>
<pre>	&lt;връщан-резултат&gt; &lt;име-на-клас&gt;::&lt;функция&gt;(вх. парам.)
	{
		// Tяло на функцията
	}</pre>
<p>За да се създаде обект, се използва името на класа като спецификатор за типа. <span id="more-226"></span>Следният ред декларира обект obj:</p>
<pre>	&lt;име-на-клас&gt; obj;</pre>
<p>Достъпът до публичните елементи на класа се осъществява с операторът точка (.). Например ако класът myclass на обекта obj има член-функция func() и член-променлива int k, то ние можем да ги използваме директно или чрез указатели по следния начин:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	class myclass{
	public:
		void func();
		int k;
	};

	void myclass::func(){
		cout &lt;&lt; k &lt;&lt; endl;
	}

	void main(){
		myclass obj;
		obj.k = 5;
		obj.func();

		myclass *p;
		p = &amp;obj;
		p-&gt;k = 12;
		p-&gt;func();
	}</pre>
<p>Вече забелязахте, че видимите обекти се дефинират чрез &#8222;public:&#8220;. Възможно е да дефинирате и скрити обекти, които не могат да се достъпват директно:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	// Заедно с дефиницията на класа
	// създаваме обект obj от тип myclass
	class myclass{
	public:
		void func();
	private:
		int k;
	} obj;

	void myclass::func(){
		k = 5;
		cout &lt;&lt; k &lt;&lt; endl;;
	}

	void main()
	{
		// obj.k = 3; ще даде грешка:
		// error C2248: 'k' : cannot access private
		//        member declared in class 'myclass'

		// Чрез публичната функция обаче
		// имаме индиректен достъп до "k"
		obj.func();
	}</pre>
<p>Конструктурът на един клас се извиква всеки път, когато се създава обект от този клас. Всякаква инициализация на данни, която е нужно да се извършим за даден обект, може да се изпълни автоматично от функцията конструктор. Той има същото име като името на класа, към който принадлежи, и не притежава тип на връщан резултат. Общият вид на конструктора е:</p>
<pre>	&lt;име-на-клас&gt;::&lt;име-на-клас&gt;(&lt;аргументи&gt;){
		//Тяло на конструктор
	}</pre>
<p>Може да създаваме повече от един конструктори, но те трябва да се различават по техните аргументи.</p>
<p>Деструкторът се извиква автоматично при разрушаването на обект от класа. Деструктора може да извежда съобщение за разрушаване на обекта или да освобождава заделената за обекта динамична памет. Деструкторът има същото име като класа, но предшествано от символа ~. Деструкторът не може да връща резултат и не може да има аргументи:</p>
<pre>	~&lt;име-на-клас&gt;::&lt;име-на-клас&gt;(){
		//Тяло на деструктор
	}</pre>
<p>Пример: Създава клас правоъгълник с публични елементи двете страни и функция за пресмятане на лицето. Дефинират се два конструктора на класа и един деструктор:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	class rectangle{
	public:
		// Два конструктора
		rectangle();
		rectangle(unsigned, unsigned);
		// Функциите могат да се описват и директно
		~rectangle(){
			cout &lt;&lt; "Object destructed" &lt;&lt; endl;
		}

		int area();
		unsigned sidea;
		unsigned sideb;
	};

	// Първият конструктор се извиква, без параметри
	// Ще поискаме потребителя да въведе страните
	rectangle::rectangle(){
		cout &lt;&lt; "Enter side a: ";
		cin &gt;&gt; sidea;
		cout &lt;&lt; "Enter side b: ";
		cin &gt;&gt; sideb;
	}

	// При втория конструктор ние сами сме указали
	// дължините на страните на правоъгълника
	rectangle::rectangle(unsigned a, unsigned b){
		sidea = a;
		sideb = b;
	}

	// Функцията, която връща лицето
	int rectangle::area(){
		return ((sidea) * (sideb));
	}

	void main(){
		// Създаваме нов обект и го инициализираме
		// чрез неговия конструктор
		rectangle *test = new rectangle();
		// Отпечатваме лицето на правоъгълника
		cout &lt;&lt; "The area of the rectangle is: ";
		cout &lt;&lt; test-&gt;area() &lt;&lt; endl;
		// Извикваме деструктора и
		// освобождаваме паметта заета от обекта
		delete test;
		cout &lt;&lt; endl &lt;&lt; endl;

		// Тук създаваме директно правоъгълник
		// със зададени страни чрез втория конструктор
		rectangle *test2 = new rectangle(5,3);
		cout &lt;&lt; "The area of the second rectangle is: ";
		cout &lt;&lt; test2-&gt;area() &lt;&lt; endl;
		delete test2;
	}</pre>
<p>Както видяхте един клас може да има множество от конструктори, които се отличават по своите параметри. Това се нарича &#8222;предефиниране&#8220; на функции. По абсолютно аналогичен начин е възможно да предефинирате член-функции на класа.</p>
<p><strong>Задача</strong>: Създайте клас триъгълник с два конструктора. Първият е без параметри и изисква въвеждане на дължините на страните от потребителя (изисква се проверка на валидност на въведените данни, т.е. дали тези страни могат да са страни на триъгълник). Вторият конструктор създава триъгълник по директно зададени дължини на страни (но отново проверява за валидност на данните). Напишете функции за изчисляване на периметър и лице на така създадения триъгълник.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/226-%d0%ba%d0%bb%d0%b0%d1%81%d0%be%d0%b2%d0%b5-%d1%87%d0%bb%d0%b5%d0%bd-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d0%be%d1%80%d0%b8-%d0%b8-%d0%b4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Оператори new и delete</title>
		<link>http://www.cphpvb.net/pik-3/221-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%b8-new-%d0%b8-delete/</link>
		<comments>http://www.cphpvb.net/pik-3/221-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%b8-new-%d0%b8-delete/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 08:01:02 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=221</guid>
		<description><![CDATA[Както вече споменахме, в обектно-ориентираното програмиране е възможно да създаваме много инстанции на един и същи &#8222;модул&#8220; (обект). Контролът върху този обект се осъществява чрез операторите new и delete. Обекти, създадени чрез операторът new, се наричат &#8222;динамични обекти&#8220;. Те се разпределят в паметта за динамични обекти (heap). Синтаксисът е следният: &#60;указател&#62; = new &#60;тип&#62;; Типа данни на указателя [...]]]></description>
			<content:encoded><![CDATA[<p>Както вече споменахме, в обектно-ориентираното програмиране е възможно да създаваме много инстанции на един и същи &#8222;модул&#8220; (обект). Контролът върху този обект се осъществява чрез операторите new и delete. Обекти, създадени чрез операторът new, се наричат &#8222;динамични обекти&#8220;. Те се разпределят в паметта за динамични обекти (heap). Синтаксисът е следният:</p>
<pre>	&lt;указател&gt; = new &lt;тип&gt;;</pre>
<p>Типа данни на указателя трябва да съвпада с типа данни на обекта, който създаваме. По този начин създаваме нова променлива, която е достъпна чрез указателя. Унищожаването на така създаден обект се осъществява, чрез операторът delete:</p>
<pre>	delete &lt;указател&gt;;</pre>
<p><span id="more-221"></span></p>
<p>Пример: Въвеждане на данни в едномерен масив и извеждане на данните му на екрана:</p>
<pre>	// Брой обекти, които ще създадем
	int numobjects;

	cout&lt;&lt;"How many objects do you want: ";
	cin &gt;&gt; numobjects;

	int *a = new int[numobjects];

	int i;
	for(i=0; i&lt;numobjects; i++){
		cout &lt;&lt; "Enter element " &lt;&lt; i &lt;&lt; ":";
		cin&gt;&gt;a[i];
	}

	for(i=0; i&lt;numobjects; i++){
		cout &lt;&lt; setw(10) &lt;&lt; a[i];
	}

	cout&lt;&lt;endl;

	// Унищожаваме масива от обекти
	delete [] a;</pre>
<p>Пример: Програма, чрез която създаваме едносвързан линеен списък, с възможност да го отпечатваме на екрана:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	struct list{
		int k;
		struct list *next;
	} *firstelement, *lastelement;

	void add(){
		if (firstelement == 0){
			firstelement = new struct list;
			cout &lt;&lt; "Enter value: ";
			cin &gt;&gt; firstelement-&gt;k;
			firstelement-&gt;next = 0;
			lastelement = firstelement;
			return;
		}
		struct list *newelement = new struct list;
		cout &lt;&lt; "Enter value: ";
		cin &gt;&gt; newelement-&gt;k;
		newelement-&gt;next = 0;

		lastelement-&gt;next = newelement;
		lastelement = newelement;
		return;
	}

	void show(){
		cout &lt;&lt; "List of elements" &lt;&lt; endl;
		struct list *p = firstelement;
		while (p != 0){
			cout &lt;&lt; p-&gt;k &lt;&lt; " -&gt; ";
			p = p-&gt;next;
		}
		cout &lt;&lt; "*" &lt;&lt; endl &lt;&lt; endl;
	}

	void main()
	{
		firstelement = 0;
		int action;
		do{
			cout &lt;&lt; "1. Add element" &lt;&lt; endl;
			cout &lt;&lt; "2. Show list" &lt;&lt; endl;
			cout &lt;&lt; "3. Exit" &lt;&lt; endl;
			cout &lt;&lt; "Choose option: ";
			cin &gt;&gt; action;
			cout &lt;&lt; endl;
			switch (action){
				case 1: add(); break;
				case 2: show(); break;
				case 3: break;
				default: cout &lt;&lt; "Invalid option" &lt;&lt; endl;
			}
		}while (action != 3);
	}</pre>
<p><strong>Задача</strong>: Преправете функцията add() така, че да не може да се въвеждат елементи в списъка от по-горния пример с повтарящи се стойности на k.</p>
<p><strong>Задача</strong>: Реализирайте функция delete(int z), която изтрива елементът от списъка в по-горния пример, който съдържа стойност k = z</p>
<p><strong>Задача</strong>: Реализирайте функция за сортиране на списъка.</p>
<p><strong>Задача</strong>: Да се напише програма, която съставя списък от факултетните номера, имената и оценката на студент и предоставя функционалност за:<br />
- Извежда данните за всички въведени студенти.<br />
- Изтриване на студент по подаден факултетен номер.<br />
- Сортиране на списъка спрямо оценка или спрямо име на студент и съответно извеждането на сортирания списък на екрана.<br />
- Показва средният успех на студентите.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/221-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%b8-new-%d0%b8-delete/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Константи, псевдоними и булев тип</title>
		<link>http://www.cphpvb.net/pik-3/205-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d0%b8-%d0%bf%d1%81%d0%b5%d0%b2%d0%b4%d0%be%d0%bd%d0%b8%d0%bc%d0%b8-%d0%b8-%d0%b1%d1%83%d0%bb%d0%b5%d0%b2-%d1%82%d0%b8%d0%bf/</link>
		<comments>http://www.cphpvb.net/pik-3/205-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d0%b8-%d0%bf%d1%81%d0%b5%d0%b2%d0%b4%d0%be%d0%bd%d0%b8%d0%bc%d0%b8-%d0%b8-%d0%b1%d1%83%d0%bb%d0%b5%d0%b2-%d1%82%d0%b8%d0%bf/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 08:00:37 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=205</guid>
		<description><![CDATA[Всички типове данни от С (int, float, double, char, указатели, и тн&#8230;), които сме разгледали дотук, са валидни и за С++. Като разширение на езика ни се предоставят и допълнителни възможности: 1. Константи: Досега, когато ни се налагаше да въвеждаме константи използвахме предпроцесора. Това не винаги е удобно, а освен това може да доведе до [...]]]></description>
			<content:encoded><![CDATA[<p>Всички типове данни от С (int, float, double, char, указатели, и тн&#8230;), които сме разгледали дотук, са валидни и за С++. Като разширение на езика ни се предоставят и допълнителни възможности:</p>
<p><strong>1. Константи</strong>: Досега, когато ни се налагаше да въвеждаме константи използвахме предпроцесора. Това не винаги е удобно, а освен това може да доведе до неочаквани грешки. Затова в С++ са въведени константи:</p>
<pre>	const &lt;тип&gt; &lt;име на променлива&gt; = &lt;стойност&gt;;</pre>
<p>Както се досещате те са много удобни при дефиниране на размерност на масиви, заделяне на памет и в всякакви подобни операции, където използваме една и съща постоянна величина на множество места в програмата. Важно е да се каже, че е задължително константите да се инициализират в момента на декларирането си.<span id="more-205"></span></p>
<p>За дефиниране на указатели към константи има една особеност &#8211; трябва указателят да се дефинира като указател към константен тип:</p>
<pre>	const int x;
	const int *px;
	px = &amp;x;</pre>
<p>Така дефинираният указател ще &#8222;сочи&#8220; адреса на променливата, но няма да може да променя нейната стойност.</p>
<p>Възможно и много често използвано е да се създадат константни указатели към не-константна променлива. По този начин указателят няма да може да променя стойността в оригиналните данни:</p>
<pre>	int x, y=2;
	const int *p;
	p = &amp;y;
	p = &amp;x;
	x = 5;
	*p = 10; // тук получаваме грешка</pre>
<p>Може да създаваме и указатели с константен адрес, които могат да променят стойността на променливата:</p>
<pre>	int x, y;
	int *const p = &amp;x;
	*p = 5;
	p = &amp;y; // грешка</pre>
<p>Накрая ще демонстрираме константен указател с константен адрес:</p>
<pre>	int x, y;
	const int *const p = &amp;x;
	*p = 5; // грешка
	p = &amp;y; // грешка</pre>
<p><strong>2. Псевдоними</strong>: Известни са още като &#8222;съотнасящи&#8220; типове (на английски reference types). Използват се за дефиниране на второ име на вече съществуващ обект:</p>
<pre>	&lt;тип&gt; &amp;&lt;име на променлива&gt; = &lt;друга променлива&gt;;</pre>
<p>Например:</p>
<pre>	int x = 5;
	int &amp;refx = x;</pre>
<p>След като са дефинирани можем да използваме псевдонимите все едно използваме оригиналните променливи. Изключително удобни са, когато искаме да предадем променливи като параметри на функция, която трябва да промени оригиналните параметри след изпълнението си (но не искаме да използваме синтаксиса на указатели). Следният пример демонстрира това:</p>
<pre>	#include "stdafx.h"
	#include "iostream.h"

	void func(int &amp;a, int &amp;b){
		a--;
		b++;
	}

	int main(int argc, char* argv[])
	{
		int a=5, b=6;
		func(a, b);

		// Ще се отпечата "a=4, b=7"
		cout &lt;&lt; "a=" &lt;&lt; a &lt;&lt; ", b=" &lt;&lt; b;
		return 0;
	}</pre>
<p>Освен това трябва да се отбележи, че когато инициализираме указател към псевдоним, то ние все едно дефинираме указател към &#8222;оригиналния&#8220; обект.</p>
<p>Възможно е както вече демонстрираното предаване на превдоним като входен параметър на функция, така и функция връщаща резултат псевдоним.</p>
<p><strong>3. Булев тип</strong>: Състои се от два елемента – стойностите true (истина) и false (лъжа). Дефинира се чрез ключовата дума bool:</p>
<pre>	bool x, y=true;
	x = false;</pre>
<p>Можем да използваме булевите променливи по същият начин както в С използвахме стойностите 0 и 1. Следният пример показва как може да използваме булева променлива като индикатор дали поредица от операции е завършила успешно:</p>
<pre>	bool completed = false;
	... // правим изчисления и евентуално променяме "completed"
	if (completed) cout &lt;&lt; "finished";
	else cout &lt;&lt; "some error occured";</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/205-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d0%b8-%d0%bf%d1%81%d0%b5%d0%b2%d0%b4%d0%be%d0%bd%d0%b8%d0%bc%d0%b8-%d0%b8-%d0%b1%d1%83%d0%bb%d0%b5%d0%b2-%d1%82%d0%b8%d0%bf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Въведение в C++</title>
		<link>http://www.cphpvb.net/pik-3/203-%d0%b2%d1%8a%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-c/</link>
		<comments>http://www.cphpvb.net/pik-3/203-%d0%b2%d1%8a%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-c/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 07:59:03 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=203</guid>
		<description><![CDATA[C++ на практика е език, който &#8222;надгражда&#8220; езика за програмиране С, като добавя нови възможности: - Обектно-ориентирано програмиране - Създаване и използване на абстрактни типове данни - Подобрения на някои съществуващи конструкции На практика вие можете да използвате всичко научено дотук от езика за програмиране С при С++ (най-малкото примерите от предишните статии са писани [...]]]></description>
			<content:encoded><![CDATA[<p>C++ на практика е език, който &#8222;надгражда&#8220; езика за програмиране С, като добавя нови възможности:</p>
<p>- Обектно-ориентирано програмиране<br />
- Създаване и използване на абстрактни типове данни<br />
- Подобрения на някои съществуващи конструкции</p>
<p>На практика вие можете да използвате всичко научено дотук от езика за програмиране С при С++ (най-малкото примерите от предишните статии са писани за компилаторът на Microsoft &#8211; Visual C++ 6.0). Затова няма да преразглеждаме вече научени езикови конструкции, а ще даваме примери за част от нововъведенията.<span id="more-203"></span></p>
<p>Ще започнем както обикновено с най-необходимите операции &#8211; Вход и изход: В библиотеката iostream.h можем да намерим два нови оператора за вход и изход &#8211; cin и cout. Тъй като вече знаете принципа на входно-изходните операции, ще демонстрираме използването им директно с пример:</p>
<pre>    #include "stdafx.h"
    #include "iostream.h"
    int main(int argc, char* argv[])
    {
        int x;
        cout &lt;&lt; "vavedete chisloto x: ";
        cin &gt;&gt; x;
        cout &lt;&lt; "vavedohte: " &lt;&lt; x &lt;&lt; '\n';
        cout &lt;&lt; "x + 2 = " &lt;&lt; x+2 &lt;&lt;'\n';
        return 0;
    }</pre>
<p>Ясно се вижда, че имаме изключително удобство при конкатенация на различни видове променливи. След като изпълните този пример може да забележите, че cin например има защита за входните данни, която решава редица проблеми, които виждахме в scanf. Следващият пример демонстрира използването на функции и указатели. В него записваме две числа и после ги отпечатваме на екрана:</p>
<pre>    #include "stdafx.h"
    #include "iostream.h"

    void read (int*, int*);
    int max(int, int);
    void printmax(int);

    int main(int argc, char* argv[]){
        int x, y;
        read(&amp;x, &amp;y);
        int maxval = max(x, y);
        printmax(maxval);
        return 0;
    }

    void read(int *x, int *y){
        cout &lt;&lt; "Please enter two numeric values: ";
        cin &gt;&gt; *x &gt;&gt; *y;
    }

    int max(int x, int y){
        if (x &gt;y) return x;
        else return y;
    }

    void printmax(int maxval){
        cout &lt;&lt; maxval &lt;&lt; " is the largest value\n";
    }</pre>
<p>Ето и един друг пример, в който използваме функцията get(), която принадлежи на входния поток cin, която взима символ и го записва в подадена променлива. Програмата демонстрира как може да прочетем поредица от символи от клавиатурата до натискане на CR и да ги преброим. Символите за нов ред и табулация не влизат в преброяването:</p>
<pre>	char ch;
	int charCnt=0;
	while (cin.get(ch)) {
		if (ch == '\n') break;
		switch (ch){
			case '\t':
			case ' ': break;
			default: ++charCnt;
				 break;
		}
	}
	cout &lt;&lt; "You typed " &lt;&lt; charCnt &lt;&lt; " characters" &lt;&lt; "\n";
	return 0;</pre>
<p>Има редица полезни функции, които ни помагат за форматирането на изходните данни. Те се намират в библиотеката iomanip.h и се наричат &#8222;манипулатори&#8220;:<br />
- setw(int): указва с каква дължина ще бъде следващото извеждане на данни на екрана. Например:</p>
<pre>	// Извежда 6 интервала последвани от текст abcd
	cout &lt;&lt; setw(10) &lt;&lt; "abcd";</pre>
<p>- setprecision(int): Указва с колко цифри ще бъдат изведени последвалите числа с плаваща запетая. Например:</p>
<pre>	double x = 12.5673;
	// Извежда "12.56"
	cout &lt;&lt; setprecision(4) &lt;&lt; x;</pre>
<p>- setiosflags(формат): Дава възможност за задаване на редица форматирания на въведения текст. Следният пример демонстрира редица от тях:</p>
<pre>	double number = 1234.45678;
	int number2 = 1234;
	// Отпечатва нов ред (вместо '\n')
	cout &lt;&lt; endl;
	cout &lt;&lt; '$';
	// Дефинира знака за запълване на празното място
	cout &lt;&lt; setfill('*');
	cout &lt;&lt; setw(12);
	// Чрез следните два реда се указва, че числото
	// ще бъде изведено с точност два знака след
	// десетичната запетая
	cout &lt;&lt; setiosflags(ios::fixed | ios:: showpoint);
	cout &lt;&lt; setprecision(2);
	// Получава се "$*****1234.46"
	cout &lt;&lt; number &lt;&lt; endl;

	// Подравняване вляво
	cout &lt;&lt; setfill('*');
	cout &lt;&lt; setw(10);
	cout &lt;&lt; resetiosflags(ios::adjustfield);
	cout &lt;&lt; setiosflags(ios::left);
	cout &lt;&lt; "test" &lt;&lt; endl;

	// Подравняване вдясно
	cout &lt;&lt; setw(10);
	cout &lt;&lt; resetiosflags(ios::adjustfield);
	cout &lt;&lt; setiosflags(ios::right);
	cout &lt;&lt; "test" &lt;&lt; endl;

	// Отпечатва числото в тип HEX
	cout &lt;&lt; setfill(' ');
	cout &lt;&lt; resetiosflags(ios::basefield);
	cout &lt;&lt; setiosflags(ios::hex);
	cout &lt;&lt; number2 &lt;&lt; endl;

	// Отпечатва числото в тип OCT
	cout &lt;&lt; setfill(' ');
	cout &lt;&lt; resetiosflags(ios::basefield);
	cout &lt;&lt; setiosflags(ios::oct);
	cout &lt;&lt; number2 &lt;&lt; endl;

	// Отпечатва числото в тип HEX
	cout &lt;&lt; setfill(' ');
	cout &lt;&lt; resetiosflags(ios::basefield);
	cout &lt;&lt; setiosflags(ios::dec);
	cout &lt;&lt; number2 &lt;&lt; endl;</pre>
<p><strong>Задача</strong>: Напишете програмата, която чете последователно числа от клавиатурата (до въвеждането на числото 0) и показва дали последното въведено число е четно или нечетно. Използвайте cin и cout за вход и изход.</p>
<p><strong>Задача</strong>: Упражнете използването на cin и cout, като преработите други вече написани на C примери.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/203-%d0%b2%d1%8a%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Накратко за обектно-ориентираното програмиране</title>
		<link>http://www.cphpvb.net/pik-3/214-%d0%bd%d0%b0%d0%ba%d1%80%d0%b0%d1%82%d0%ba%d0%be-%d0%b7%d0%b0-%d0%be%d0%b1%d0%b5%d0%ba%d1%82%d0%bd%d0%be-%d0%be%d1%80%d0%b8%d0%b5%d0%bd%d1%82%d0%b8%d1%80%d0%b0%d0%bd%d0%be%d1%82%d0%be-%d0%bf%d1%80/</link>
		<comments>http://www.cphpvb.net/pik-3/214-%d0%bd%d0%b0%d0%ba%d1%80%d0%b0%d1%82%d0%ba%d0%be-%d0%b7%d0%b0-%d0%be%d0%b1%d0%b5%d0%ba%d1%82%d0%bd%d0%be-%d0%be%d1%80%d0%b8%d0%b5%d0%bd%d1%82%d0%b8%d1%80%d0%b0%d0%bd%d0%be%d1%82%d0%be-%d0%bf%d1%80/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 07:58:29 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=214</guid>
		<description><![CDATA[За да обясним понятието &#8222;обектно-ориентирано програмиране&#8220; е добре да опишем какви програми писахме на езика за програмиране С досега: 1. Скриптови програми: Последователно изпълнение на предварително зададена поредица от операции. 2. Процедурно програмиране: Възможност за &#8222;разклоняване&#8220; на програмата, така че тя да извършва различни последователности от операции (процедури или както споменахме в т.1 &#8211; скриптове), в [...]]]></description>
			<content:encoded><![CDATA[<p>За да обясним понятието &#8222;обектно-ориентирано програмиране&#8220; е добре да опишем какви програми писахме на езика за програмиране С досега:</p>
<p>1. Скриптови програми: Последователно изпълнение на предварително зададена поредица от операции.</p>
<p>2. Процедурно програмиране: Възможност за &#8222;разклоняване&#8220; на програмата, така че тя да извършва различни последователности от операции (процедури или както споменахме в т.1 &#8211; скриптове), в зависимост от въведени данни от потребителят. След изпълнение на дадена процедура програмата се &#8222;връща&#8220; на мястото, където процедурата е извикана.</p>
<p>3. Модулно-процедурно програмиране: Предоставя възможност за обединяване на различни процедури в т.нар. &#8222;модули&#8220;. По този начин разделяме програмата на различни логически части, които се свързват почежду си чрез т.нар. &#8222;procedure calls&#8220;.<span id="more-214"></span></p>
<p>Обектно-ориентираното програмиране е подход, при който данните и алгоритмите за работа с тях се комбинират в цялостен “обект”, който може да бъде използван в множество програми. Основните концепции на ООП са обекти, класове, наследственост, полиморфизъм и динамично заделяне на памет.</p>
<p>Разпространена е тенденцията, че в разработката на софтуер ние се стремим да използваме колкото се може повече готови разработени функционалности и по този начин да &#8222;сглабяме&#8220; програми, а не да ги пишем наново. Така ние всъщност използваме готови обекти и работим с тях чрез &#8222;интерфейс&#8220;. Предоставянето на достъп до обекта само чрез неговия интерфейс от съобщения се нарича капсулация. Това е подход, при който ние показваме само функциите и данните от даден обект, които трябва да бъдат видими при работа с него. Всичкият останал код се &#8222;капсулира&#8220;, т.е. скрива и защитава. </p>
<p>Класовете описват конструкцията на обектите и методите на работа с него. Класът сам по себе си не е обект, а просто шаблон, който показва как ще изглежда даден обект. Ние можем да създаваме множество обекти по шаблона на един клас. Схемата за достъп прилича много на тази при вече познатите структури. Може да се каже, че класовете всъщност са естествено продължение на идеята за структурния тип.</p>
<p>Наследяването е друга основна черта на обектно ориентираното програмиране. Тя е именно споменатата вече възможност да не пренаписваме код, а да го използваме наготово. Чрез наследяването ние взимаме кода на вече написан клас и единствено разширяваме или променяме неговата функционалност. Така ние моделираме и изграждаме системи от обекти.</p>
<p>Полиморфизмът ни дава възможност да разглеждаме един обект в различни форми. В C++ полиморфизмът се реализира чрез виртуалните функции.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/214-%d0%bd%d0%b0%d0%ba%d1%80%d0%b0%d1%82%d0%ba%d0%be-%d0%b7%d0%b0-%d0%be%d0%b1%d0%b5%d0%ba%d1%82%d0%bd%d0%be-%d0%be%d1%80%d0%b8%d0%b5%d0%bd%d1%82%d0%b8%d1%80%d0%b0%d0%bd%d0%be%d1%82%d0%be-%d0%bf%d1%80/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Допълнителни задачи към упражнения 2 и 3</title>
		<link>http://www.cphpvb.net/pik-3/217-%d0%b4%d0%be%d0%bf%d1%8a%d0%bb%d0%bd%d0%b8%d1%82%d0%b5%d0%bb%d0%bd%d0%b8-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8-%d0%ba%d1%8a%d0%bc-%d1%83%d0%bf%d1%80%d0%b0%d0%b6%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-2-%d0%b8-3/</link>
		<comments>http://www.cphpvb.net/pik-3/217-%d0%b4%d0%be%d0%bf%d1%8a%d0%bb%d0%bd%d0%b8%d1%82%d0%b5%d0%bb%d0%bd%d0%b8-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8-%d0%ba%d1%8a%d0%bc-%d1%83%d0%bf%d1%80%d0%b0%d0%b6%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-2-%d0%b8-3/#comments</comments>
		<pubDate>Sat, 01 Nov 2008 09:12:38 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=217</guid>
		<description><![CDATA[Задача: Дадена е матрица с N реда и M стълба, която може да съдържа елементи числата 0 и 1. Нека тази матрица е лабиринт, в който 0 означава, че има път, а 1 че има препятствие. Елемент (0, 0) се нарича вход, а елемент (N, M) изход от лабиринта. В лабиринта можем да се движим само по хоризонтала и вертикала. Напишете [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Задача</strong>: Дадена е матрица с N реда и M стълба, която може да съдържа елементи числата 0 и 1. Нека тази матрица е лабиринт, в който 0 означава, че има път, а 1 че има препятствие. Елемент (0, 0) се нарича вход, а елемент (N, M) изход от лабиринта. В лабиринта можем да се движим само по хоризонтала и вертикала. Напишете програма с меню и следните функции:<br />
- Въвежда елементите на матрицата от клавиатурата.<br />
- Генерира случаен лабиринт.<br />
- Обхожда лабиринта и намира възможен път (ако има такъв).<br />
- Намира най-краткият от възможните пътища (ако има такива).</p>
<p><strong>Задача</strong>: Даден е едномерен масив от тип int. Запълнете масива с произволни числа и реализирайте функция, която намира най-голямото възможно число, образувано от елементите на масива.</p>
<p><strong>Задача</strong>: В текстов файл са записани имена, телефони и e-mail адреси в следния формат:</p>
<p><em>Ivan, 0888555666, ivan@abv.bg<br />
Petko, 0899555666, petko@yahoo.com<br />
&#8230;</em></p>
<p>Напишете програма, която прочита файла и:<br />
- Изважда имената и телефоните и ги записва в нов файл phonebook.txt, като всяко име и телефон са на отделен ред.<br />
- Изважда всички e-mail адреси и ги записва във файл maillist.txt, като всеки адрес е на нов ред.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/217-%d0%b4%d0%be%d0%bf%d1%8a%d0%bb%d0%bd%d0%b8%d1%82%d0%b5%d0%bb%d0%bd%d0%b8-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87%d0%b8-%d0%ba%d1%8a%d0%bc-%d1%83%d0%bf%d1%80%d0%b0%d0%b6%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-2-%d0%b8-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Функции за разпределение на паметта</title>
		<link>http://www.cphpvb.net/pik-3/194-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%b7%d0%b0-%d1%80%d0%b0%d0%b7%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d0%b5%d1%82%d1%82%d0%b0/</link>
		<comments>http://www.cphpvb.net/pik-3/194-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%b7%d0%b0-%d1%80%d0%b0%d0%b7%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d0%b5%d1%82%d1%82%d0%b0/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 14:41:59 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=194</guid>
		<description><![CDATA[Всеки компютър разполага с определено количество свободна памет. За да се използува ефективно тя трябва да се разпределя динамично. В С имаме възможност да променяме подразбиращият се размер на стека по време на изполнението на програмата. Програмистът обаче сам трябва да се грижи да предпазва стека от препълване. Ще разгледаме две от функциите за разпределение [...]]]></description>
			<content:encoded><![CDATA[<p>Всеки компютър разполага с определено количество свободна памет. За да се използува ефективно тя трябва да се разпределя динамично. В С имаме възможност да променяме подразбиращият се размер на стека по време на изполнението на програмата. Програмистът обаче сам трябва да се грижи да предпазва стека от препълване.</p>
<p>Ще разгледаме две от функциите за разпределение на паметта от високо ниво &#8211; malloc, calloc и free.</p>
<p>1. malloc: Резервира блок памет и връща указател към блока:</p>
<pre>	int *p = (int *)malloc(unsigned bytes);</pre>
<p>Чрез bytes указваме точно колко байта памет искаме да резервираме. Ако няма достатъчно памет в указателя p ще се запише NULL. Имайте в предвид, че ако се опитате да записвате информация чрез такъв указател програмата ще завърше с фатална грешка, затова винаги проверявайте резултатът от malloc! <span id="more-194"></span></p>
<p>2. calloc: Резервира блок памет и нулира всичките му байтове:</p>
<pre>	int *p = (int *)calloc(unsigned number, unsigned elnumber);</pre>
<p>Number e броя елементи, за които се заделя памет, а elnumber е типа данни на тези елементи. Например:</p>
<pre>	// Заделя и нулира памет за 10 елемента от тип float
	int *p = (int *)calloc(10, sizeof(float));</pre>
<p>3. free: Овобождава блока памет заделен чрез malloc или calloc:</p>
<pre>	free(int *p);</pre>
<p><strong>Пример</strong>: Реализираме стек с използване на указатели, като предварително заделяме памет за него:</p>
<pre>	#include "stdafx.h"
	#include "stdio.h"
	#include "stdlib.h"
	#define STACKSIZE 5

	// Ukazatel kam chisloto i
	int *pi;

	// Nachalo na steka
	int *pimin;

	// vkarvane na element v steka
	void push(){
		if (pi == pimin + STACKSIZE){
			printf("Stack is full! Please pop some elements\n\n");
			return;
		}
		else{
			int num;
			printf("Enter number to push in stack: ");
			scanf("%d", &amp;num);
			*pi = num;
			pi++;
			return;
		}
	}

	// premahvane na element ot steka
	void pop(){
		if (pi == pimin){
			printf("Stack is empty!\n\n");
			return;
		}
		else{
			pi--;
			printf("Last element in stack: %d\n\n", *pi);
			return;
		}
	}

	int main(int argc, char* argv[])
	{
		// Zadeliame pamet za STACKSIZE na broi elementa s razmer int
		pimin = (int *)calloc(STACKSIZE, sizeof(int));
		pi = pimin;

		int action;
		do{
			printf("1. Push number to stack\n");
			printf("2. Pop number to stack\n");
			printf("3. Exit\n\n");
			printf("Choose action: ");
			scanf("%d", &amp;action);
			switch(action){
				case 1:  push();
					break;
				case 2:  pop();
					break;
				case 3:  break;
				default: printf("invalid option\n\n\n");
					break;
			}
		} while(action != 3);

		free(pimin);
		return 0;
	}</pre>
<p><strong>Задача</strong>: Приложете техниката описана в статията <a href="http://www.cphpvb.net/pik-3/160-%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b8-%d1%81%d0%b2%d1%8a%d1%80%d0%b7%d0%b0%d0%bd%d0%b8-%d1%81-%d0%b8%d0%b7%d0%bf%d0%be%d0%bb%d0%b7%d0%b2%d0%b0%d0%bd%d0%b5%d1%82%d0%be-%d0%bd%d0%b0-scanf/">Проблеми свързани с използването на scanf</a> в горния пример.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/194-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%b7%d0%b0-%d1%80%d0%b0%d0%b7%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d0%b5%d1%82%d1%82%d0%b0/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Работа с файлове от ниско ниво (UNIX стил)</title>
		<link>http://www.cphpvb.net/pik-3/189-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0-%d1%81-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d0%b5-%d0%be%d1%82-%d0%bd%d0%b8%d1%81%d0%ba%d0%be-%d0%bd%d0%b8%d0%b2%d0%be-unix-%d1%81%d1%82%d0%b8%d0%bb/</link>
		<comments>http://www.cphpvb.net/pik-3/189-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0-%d1%81-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d0%b5-%d0%be%d1%82-%d0%bd%d0%b8%d1%81%d0%ba%d0%be-%d0%bd%d0%b8%d0%b2%d0%be-unix-%d1%81%d1%82%d0%b8%d0%bb/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 13:43:48 +0000</pubDate>
		<dc:creator>Филип Петров</dc:creator>
				<category><![CDATA[С/C++]]></category>

		<guid isPermaLink="false">http://www.cphpvb.net/?p=189</guid>
		<description><![CDATA[Функциите open, close, creat, unlink, read, write и lseek предоставят небуфериран достъп до данните във файловете. Това означава, че ще е нужно ние сами да се грижим за създаването на съответен буфер. Използват се предимно при UNIX -базирани операционни системи (Linux или BSD например). 1. open: Отваря файл с режим на достъп четене (0), запис [...]]]></description>
			<content:encoded><![CDATA[<p>Функциите open, close, creat, unlink, read, write и lseek предоставят небуфериран достъп до данните във файловете. Това означава, че ще е нужно ние сами да се грижим за създаването на съответен буфер. Използват се предимно при UNIX -базирани операционни системи (Linux или BSD например).</p>
<p>1. open: Отваря файл с режим на достъп четене (0), запис (1) или четене+запис:</p>
<pre>	int fd = open(char *path, int flags, mode_t mode);</pre>
<p>Променливата fd се напича дескриптор на файла. Ако отварянето на файла не е възможно, то дескриптора ще получи стойност -1. Входния параметър name е символен низ, който описва пътя до файла в операционната система. Флаговете (flags) са следните:<br />
O_RDONLY &#8211; само за четене.<br />
O_WRONLY &#8211; само за запис.<br />
O_CREAT &#8211; Създава файла ако той не съществува.<br />
O_TRUNC &#8211; Изтрива съдържанието на файла.<br />
&#8230;<span id="more-189"></span></p>
<p>Входния параметър mode определя режима на достъп. Той е валиден за UNIX операционни системи и се игнорира в DOS/WINDOWS:<br />
S_IRUSR &#8212; Read for owner.<br />
S_IWUSR &#8212; Write for owner.<br />
S_IRGRP &#8212; Read for group.<br />
S_IROTH &#8212; Read for other.<br />
&#8230;</p>
<p>Следният пример демонстрира отваряне на файл:</p>
<pre>	int fd;
	if ((fd = open("test.txt", O_RDONLY, 0)) &lt; 0) printf("Open failed");</pre>
<p>2. close: Затваря файл, отворен чрез open за четене и запис и освобождава дескриптора. Следният пример отваря и затваря файл:</p>
<pre>	int fd = open("test.txt", 0);
	if (fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC,
                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH    )) &lt; 0)
				              printf("Open failed");
	else close(fd);</pre>
<p>Функцията close връща 0 при успешно изпълнение и -1 при грешка. Също както fclose се осигурява правилното записване на файла с всички актуализирани данни.</p>
<p>3. creat: Отваря нов файл за запис. Ако файла вече съществува, то изтрива всичката информация в него. Има следния синтаксис:</p>
<pre>	int fd = creat(char *name, int mode);</pre>
<p>Аналогията с open е очевидна. Тази функция е на практика излязла от употреба, защото е еквивалентна на open(&#8222;name&#8220;, O_WRONLY, 0)</p>
<p>4. unlink: Абсолютно аналогична на remove функция. Като входен параметър приема името на файла като символен низ и връща -1 при грешка.</p>
<p>5. read: Функцията за четене на информация от файл:</p>
<pre>	read(int fd, char *buffer, int num);</pre>
<p>Fd е файловия дескриптор. Buffer e указател към символен низ, в който се записват данните. Num е броя байтове на блока, който ще бъде прочетен (трябва да е равен или по-малък от размерността на буфера). Функцията връща 0 при успех и -1 при грешка.</p>
<p>6. write: Функцията за запис на информация във файл:</p>
<pre>	write(int fd, char *buffer, int num);</pre>
<p>Входните данни са аналогични както при read. Резултатът отново е 0 при успех и -1 при грешка.</p>
<p>7. lseek: Променя текущата позиция във файла:</p>
<pre>	fseek(int fd, long offset, int mode);</pre>
<p>Fd е файловият дескриптор, offset показва броя байтове, а mode указва типа на адресното преместване (0 &#8211; от началото, 1 &#8211; от текущата позиция или 2 &#8211; от края на файла &#8222;назад&#8220;).</p>
<p>Следната програма е еквивалентна на програмата cp под UNIX (копира файлове):</p>
<pre>	/*fileio.c
	* Tom Kelliher
	*
	* This program demonstrates how to do low-level file I/O in C.  This
	* program implements a simple version of Unix's cp command.  Two
	* filename are expected on the command line.  The first file is the
	* name of the file to be copied, the second is the file to be created.
	*/

	#include &lt;sys/types.h&gt;
	#include &lt;sys/stat.h&gt;
	#include &lt;fcntl.h&gt;
	#include &lt;stdio.h&gt;
	#include &lt;stdlib.h&gt;
	#include &lt;unistd.h&gt;

	/* Prototypes. */
	void pdie(const char *);
	void die(const char *);

	#define BUFFER_SIZE 1024   /* Size of the read/write buffer. */

	int main(int argc, char* argv[])
	{
		int rfd;   /* Read file descriptor. */
		int wfd;   /* Write file descriptor. */
		char buffer[BUFFER_SIZE];   /* Read/Write buffer. */
		char *bp;   /* Pointer into write buffer. */
		int bufferChars;   /* Number of bytes remaining to be written. */
		int writtenChars;  /* Number of bytes written on last write. */

		if (argc != 3)
		{
			printf("Two filenames expected.\n");
			exit(1);
		}

		/* Open file to be copied. */
		if ((rfd = open(argv[1], O_RDONLY, 0)) &lt; 0)
			pdie("Open failed");

		/* Open file to be created. */
		if ((wfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC,
			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) &lt; 0)
						pdie("Open failed");

		while (1)
		{
			/* Normal case --- some number of bytes read. */
			if ((bufferChars = read(rfd, buffer, BUFFER_SIZE)) &gt; 0)
			{
				bp = buffer;   /* Pointer to next byte to write. */

				/*
				Since we can't guarantee that all the bytes will be written
				in a single write(), this code must be written such that
				several write()'s can possibly be called.
				*/
				while (bufferChars &gt; 0)
				{
					if ((writtenChars = write(wfd, bp, bufferChars)) &lt; 0)
					pdie("Write failed");

					bufferChars -= writtenChars;   /* Update. */
					bp += writtenChars;
				}
			}
			else if (bufferChars == 0)   /* EOF reached. */
				break;
			else   /* bufferChars &lt; 0 --- read failure. */
				pdie("Read failed");
		}

		close(rfd);
		close(wfd);
		return 0;
	}

	// pdie --- Print error message, call perror, and die.
	void pdie(const char *mesg) {
		perror(mesg);
		exit(1);
	}

	// die --- Print error message and die.
	void die(const char *mesg) {
		fputs(mesg, stderr);
		fputc('\n', stderr);
		exit(1);
	}</pre>
<p><strong>Задача</strong>: Препишете този пример, така че да работи с компилатора на Visual Studio 6 (Console Application).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cphpvb.net/pik-3/189-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0-%d1%81-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2%d0%b5-%d0%be%d1%82-%d0%bd%d0%b8%d1%81%d0%ba%d0%be-%d0%bd%d0%b8%d0%b2%d0%be-unix-%d1%81%d1%82%d0%b8%d0%bb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

