<?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>pamiętnik programisty &#187; C++</title>
	<atom:link href="http://piotr.doniec.eu/devlog/category/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://piotr.doniec.eu/devlog</link>
	<description></description>
	<lastBuildDate>Sun, 25 Jul 2010 12:54:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Z C++ zagadka nr 4</title>
		<link>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:50:24 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[common error]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=532</guid>
		<description><![CDATA[Mając przedstawioną poniżej strukturę danych i kontener zawierający wskaźniki, wykonać operację/metodę methodA na rzecz obiektu obj_ posługując się iteratorem: class Foo { public: methodA() { printf(&#34;Wykonano...\n&#34;); } } struct data_t { int i_; Foo* obj_; } std::list&#60;data_t*&#62; data_; for(std::list&#60;data_t*&#62;::iterator i = data_.begin(); i != data_.end(); i++ ) { // operacje } W jaki sposób wykonać]]></description>
			<content:encoded><![CDATA[<p>Mając przedstawioną poniżej strukturę danych i kontener zawierający wskaźniki, wykonać operację/metodę methodA na rzecz obiektu obj_ posługując się iteratorem:</p>
<pre class="brush: cpp">
class Foo {
public:
  methodA() {
    printf(&quot;Wykonano...\n&quot;);
  }
}

struct data_t {
  int i_;
  Foo* obj_;
}

std::list&lt;data_t*&gt; data_;

for(std::list&lt;data_t*&gt;::iterator i  = data_.begin(); i != data_.end(); i++ ) {
   // operacje
}
</pre>
<p>W jaki sposób wykonać blok operacji ? Możliwości mamy kilka:</p>
<pre class="brush: cpp">
/* 1 */ i-&gt;obj_-&gt;methodA();
/* 2 */ *i-&gt;obj_-&gt;methodA();
/* 3 */ (*i)-&gt;obj_-&gt;methodA();
</pre>
<p>Rozwiązanie zagadki jest proste, ale wymaga znajomości priorytetów operatorów. Pierwsze wywołania jest całkowicie błędne, ponieważ lista przecowuje wskaźniki do strkutury, a nie samą strukturę. Zatem należy najpier wyłuskać strukturę znajdującą się pod wskazywanym adresem i dopiero wtedy wykonać metodę. Okazuje się że rowiązania 2 również jest nie poprawne, właśnie ze względu na priorytety operatorów. Dopiero numer 3 daje zamierzony efekt. Na szczęście błąd ujawnia się na etapie kompilacji&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uruchamianie metod klas w nowych wątkach w c++ i pthreads</title>
		<link>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 10:47:17 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[pthreads]]></category>
		<category><![CDATA[qnx]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[wielowątkowość]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=471</guid>
		<description><![CDATA[Podczas pisania kolejnego projektu w języku c++ natknąłem się na interesujący problem. Program docelowo miał działać na systemie czasu rzeczywistego zatem jego celem było również zapoznanie z różnymi mechanizmami RTOS. Pierwszy problem pojawił się przy korzystaniu z mechanizmu wielowątkowości, pewnie byśmy się nie dowiedzieli o jego istnieniu gdybyśmy nie zdecydowali się na programowanie obiektowe, ale]]></description>
			<content:encoded><![CDATA[<p><img src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/04/logo.gif" alt="qnx_rtos" title="qnx_rtos" width="106" height="45" class="alignright size-full wp-image-483" />Podczas pisania kolejnego projektu w języku c++ natknąłem się na interesujący problem. Program docelowo miał działać na systemie czasu rzeczywistego zatem jego celem było również zapoznanie z różnymi mechanizmami RTOS. Pierwszy problem pojawił się przy korzystaniu z mechanizmu wielowątkowości, pewnie byśmy się nie dowiedzieli o jego istnieniu gdybyśmy nie zdecydowali się na programowanie obiektowe, ale po kolei&#8230;<br />
<span id="more-471"></span><br />
Każdy kto programował w C++ korzystając z biblioteki Boost::Threads napewno wie że aby uruchomić metodę obiektu w nowym wątku wystarczy przeciążyć operator () i każdy obiekt takiej klasy zaczyna z powodzeniem udawać funkcję. Dzięki temu można taki obiekt przekazać do konstruktora boost::thread. Poniższy przykład obrazuje taką sposób działania:</p>
<pre class="brush: cpp">
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided &quot;as is&quot; without express or implied warranty.

#include &lt;boost/thread/thread.hpp&gt;;
#include &lt;;boost/thread/xtime.hpp&gt;;
#include &lt;iostream&gt;;

struct thread_alarm
{
    thread_alarm(int secs) : m_secs(secs) { }
    void operator()()
    {
        boost::xtime xt;
        boost::xtime_get(&amp;xt, boost::TIME_UTC);
        xt.sec += m_secs;

        boost::thread::sleep(xt);

        std::cout &lt;&lt; &quot;alarm sounded...&quot; &lt;&lt; std::endl;
    }

    int m_secs;
};

int main(int argc, char* argv[])
{
    int secs = 5;
    std::cout &lt;&lt; &quot;setting alarm for 5 seconds...&quot; &lt;&lt; std::endl;
    thread_alarm alarm(secs);
    boost::thread thrd(alarm);
    thrd.join();
}
</pre>
<p>Jednak ten sposób nie działa w przypadku korzystania z natywnego mechanizmu wielowątkowości dostępnego w każdym systemie *nix. Biblioteka pthreads nie radzi sobie z wywołaniem przeciążonego operatora (). Problem trzeba było rozwiązać jak najszybciej, żeby projekt mógł ruszy dalej. Dlatego powstał ten sprytny &#8222;work-around&#8221; umożliwiający uruchomienie dowolnej metody obiektu w nowym wątku. Jest to właściwie funkcja proxy, takie proste a ułatwia życie:</p>
<pre class="brush: cpp">
template&lt;class T&gt;
struct ThreadParams
{
	T *obj;
	void *params;
};

template&lt;class T, void* (T::*method)(void*)&gt;
void* run_thread(void *params)
{
	ThreadParams&lt;T&gt; *t = static_cast&lt;ThreadParams&gt;&lt;T*&gt;(params);
	T* obj = static_cast&lt;T*&gt;(t-&gt;obj);
	(obj-&gt;*method)(t-&gt;params);
	return NULL;
}
</pre>
<p>Dodatkowy wkład pracy jaki należy włożyć aby wykorzystać powyższy kod ogranicza się właściwie tylko do wypełnienia struktury ThreadParams:</p>
<pre class="brush: cpp">
class Test
{
public:
	void* fun(void* params) {
	printf(&quot;Hello World! \n&quot;);
	printf(&quot;Params: %d\n&quot;, reinterpret_cast&lt;int&gt;(params));
	pthread_exit(NULL);
	}
 };

 int main() {

	pthread_t tid;
	void* status;
	Test test;
	ThreadParams&lt;Test&gt; params;

	params.obj = &amp;test;
	params.params = reinterpret_cast&lt;void&gt;(123);

	pthread_create(&amp;tid, NULL, run_thread&lt;Test, &amp;Test::fun&gt;, (void*)(&amp;params));
	pthread_join(tid, &amp;status);
 }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scons &#8211; alternatywa dla Make, Qmake i podobnych</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 12:35:20 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Inne]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=404</guid>
		<description><![CDATA[Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować. Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual]]></description>
			<content:encoded><![CDATA[<p>Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować.<br />
Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual C++ Compiler, można zadecydować który z nich ma zostać użyty.<br />
Najprostszy plik z instrukcją zdudowania programu to 1 linia:</p>
<pre class="brush: python">
Program(&#039;main.cpp&#039;)
</pre>
<p>Na Windows domyślnie zostanie wykorzystany (o ile dostępny) kompilator Microsoftu. Jeśli jednak chcemy użyć g++, wystarczy dopisać jeszcze jedną linię:</p>
<pre class="brush: python">
env = Environment(tools = [&#039;mingw&#039;], CC = &#039;gcc&#039;, CCFLAGS = &#039;-O2&#039;)
env.Program(&#039;main.cpp&#039;)
</pre>
<p>Piewsze lody przełamane, kolejne próby będą sprawdzały łatwość dołączania zewnętrzych bibliotek jak boost czy qt.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Przezroczyste okienka z WinAPI</title>
		<link>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 12:24:08 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[winapi]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=270</guid>
		<description><![CDATA[Wraz z pojawieniem się systemu Windows 2000, pojawiły się nowe funkcje systemowego API. Jedną z nich jest możliwość tworzenia okien o dowolnym stopniu przezroczystości. Efekt jest dość ciekawy i sporo programów ma możliwość ustawienia przezroczystości własnego okienka. Moim celem było umożliwienie sterowania przezroczystością okien centralnie z jednego programu i to nie zależnie od tego czy]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-339 alignleft" title="transparent_windows2" src="http://piotr.doniec.eu/devlog/wp-content/uploads/2009/10/transparent_windows21.jpg" alt="Przezroczyste okna z winAPI" width="244" height="220" />Wraz z pojawieniem się systemu Windows 2000, pojawiły się nowe funkcje systemowego API. Jedną z nich jest możliwość tworzenia okien o dowolnym stopniu przezroczystości. Efekt jest dość ciekawy i sporo programów ma możliwość ustawienia przezroczystości własnego okienka. Moim celem było umożliwienie sterowania przezroczystością okien centralnie z jednego programu i to nie zależnie od tego czy okno takie zostało do tego przystosowane czy też nie. Po przeczytaniu tego wpisu, każdy samodzielnie będzie mógł napisać podobną aplikację</p>
<p><span id="more-270"></span></p>
<p>Aby istniała możliwość ustawiania przezroczystości dla okna, musi być ono utworzone w sposób do tego przystosowany. Wystarczy skorzystać z innej funkcji tworzącej okno, nie <code>CreateWindow</code>, a <code>CreateWindowEx</code></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HWND CreateWindowEx<span style="color: #009900;">&#40;</span><br />
&nbsp; DWORD dwExStyle<span style="color: #339933;">,</span><br />
&nbsp; LPCTSTR lpClassName<span style="color: #339933;">,</span><br />
&nbsp; LPCTSTR lpWindowName<span style="color: #339933;">,</span><br />
&nbsp; DWORD dwStyle<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> x<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> y<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> nWidth<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> nHeight<span style="color: #339933;">,</span><br />
&nbsp; HWND hWndParent<span style="color: #339933;">,</span><br />
&nbsp; HMENU hMenu<span style="color: #339933;">,</span><br />
&nbsp; HINSTANCE hInstance<span style="color: #339933;">,</span><br />
&nbsp; LPVOID lpParam<br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>To co umożliwia później modyfikacje przezroczystości jest ukryte w ramach dodatkowego stylu okna, podawanego poprzez argument <code>dwExStyle</code>. Lista dopuszczalnych wartości jest długa, ale warto się z nią zapoznać. W tym konkretnym przypadku należy zainteresować się wartością <code>WS_EX_LAYERED</code>, utworzone wtedy okno będzie tzw. Layered Window, które obsługuje modyfikacje przezroczystości. Do ustawienia nowej wartości kanału alpha służy <code>SetLayeredWindowAttributes(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWROD dwFlags)</code> &#8211; szczegóły w dokumentacji.<br />
Pełny kod tworzący przykładowe, półprzezroczyste okno:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;windows.h&gt;</span><br />
<br />
LRESULT CALLBACK WndProc<span style="color: #009900;">&#40;</span>HWND<span style="color: #339933;">,</span> UINT<span style="color: #339933;">,</span> WPARAM<span style="color: #339933;">,</span> LPARAM<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #993333;">int</span> WINAPI WinMain<span style="color: #009900;">&#40;</span>HINSTANCE hInstance<span style="color: #339933;">,</span> &nbsp; HINSTANCE hPrevInstance<span style="color: #339933;">,</span><br />
LPSTR lpCmdLine<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> nCmdShow<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; MSG msg<span style="color: #339933;">;</span><br />
&nbsp; HWND hwnd<span style="color: #339933;">;</span><br />
&nbsp; WNDCLASSEX wcx<span style="color: #339933;">;</span><br />
&nbsp;<br />
&nbsp; wcx.<span style="color: #202020;">cbSize</span> <span style="color: #339933;">=</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>wcx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">style</span> <span style="color: #339933;">=</span> CS_HREDRAW <span style="color: #339933;">|</span> CS_VREDRAW<span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">lpfnWndProc</span> <span style="color: #339933;">=</span> WndProc<span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">cbClsExtra</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">cbWndExtra</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hInstance</span> <span style="color: #339933;">=</span> hInstance<span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hIcon</span> <span style="color: #339933;">=</span> LoadIcon<span style="color: #009900;">&#40;</span>NULL<span style="color: #339933;">,</span> IDI_APPLICATION<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hCursor</span> <span style="color: #339933;">=</span> LoadCursor<span style="color: #009900;">&#40;</span>NULL<span style="color: #339933;">,</span> IDC_ARROW<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hbrBackground</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>HBRUSH<span style="color: #009900;">&#41;</span>GetStockObject<span style="color: #009900;">&#40;</span>WHITE_BRUSH<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">lpszMenuName</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;MainMenu&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">lpszClassName</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;MainWClass&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hIconSm</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>HICON<span style="color: #009900;">&#41;</span>LoadImage<span style="color: #009900;">&#40;</span>hInstance<span style="color: #339933;">,</span> MAKEINTRESOURCE<span style="color: #009900;">&#40;</span>5<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> IMAGE_ICON<span style="color: #339933;">,</span><br />
&nbsp; GetSystemMetrics<span style="color: #009900;">&#40;</span>SM_CXSMICON<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> GetSystemMetrics<span style="color: #009900;">&#40;</span>SM_CYSMICON<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>UINT<span style="color: #009900;">&#41;</span>LR_DEFAULTCOLOR<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; RegisterClassEx<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>wcx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; hwnd <span style="color: #339933;">=</span> CreateWindowEx<span style="color: #009900;">&#40;</span>WS_EX_LAYERED<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;MainWClass&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;Sample&quot;</span><span style="color: #339933;">,</span> WS_OVERLAPPEDWINDOW<span style="color: #339933;">,</span> CW_USEDEFAULT<span style="color: #339933;">,</span> &nbsp;CW_USEDEFAULT<span style="color: #339933;">,</span> CW_USEDEFAULT<span style="color: #339933;">,</span> CW_USEDEFAULT<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>HWND<span style="color: #009900;">&#41;</span>NULL<span style="color: #339933;">,</span> &nbsp;<span style="color: #009900;">&#40;</span>HMENU<span style="color: #009900;">&#41;</span>NULL<span style="color: #339933;">,</span> hInstance<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>LPVOID<span style="color: #009900;">&#41;</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; ShowWindow<span style="color: #009900;">&#40;</span>hwnd<span style="color: #339933;">,</span> nCmdShow<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; SetLayeredWindowAttributes<span style="color: #009900;">&#40;</span>hwnd<span style="color: #339933;">,</span> 0<span style="color: #339933;">,</span> 180<span style="color: #339933;">,</span> LWA_ALPHA<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; UpdateWindow<span style="color: #009900;">&#40;</span>hwnd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>GetMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> &nbsp;0<span style="color: #339933;">,</span> 0<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; TranslateMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; DispatchMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">return</span> msg.<span style="color: #202020;">wParam</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
LRESULT CALLBACK WndProc<span style="color: #009900;">&#40;</span>HWND hwnd<span style="color: #339933;">,</span> UINT uMsg<span style="color: #339933;">,</span> WPARAM wParam<span style="color: #339933;">,</span> LPARAM lParam<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span>uMsg<span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> WM_CREATE<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> WM_PAINT<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> WM_DESTROY<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; PostQuitMessage<span style="color: #009900;">&#40;</span>0<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> DefWindowProc<span style="color: #009900;">&#40;</span>hwnd<span style="color: #339933;">,</span> uMsg<span style="color: #339933;">,</span> wParam<span style="color: #339933;">,</span> lParam<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>To co należy zrobić, aby kontrolować przezroczystość okien innych niż własne przedstawia się następująco:</p>
<ol>
<li>1. Pobrać wszystkie otwarte okna typu top-level</li>
<li>2. Nadać oknom styl <code>dwExStyle</code></li>
<li>3. Zmienić wartość kanału alpha</li>
</ol>
<p><strong>1. Pobrać wszystkie otwarte okna typu top-level</strong><br />
Dobrym pomysłem wydaje się pobranie uchwytu do rodzica wszystkich okien(Desktop/Pulpit) i przejście w pętli po liście jego dzieci (jak wiadomo każde okno ma kilka przydatnych wskaźników, między innymi do okna-brata). Mogłoby to wyglądać tak:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HWND hDesktop <span style="color: #339933;">=</span> GetDesktopWindow<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
HWND hChild <span style="color: #339933;">=</span> GetWindow<span style="color: #009900;">&#40;</span>hDesktop<span style="color: #339933;">,</span> GW_CHILD<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
HWND hTemp<span style="color: #339933;">;</span><br />
<span style="color: #808080; font-style: italic;">/* ... */</span><br />
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>hTemp <span style="color: #339933;">!=</span> GetWindow<span style="color: #009900;">&#40;</span>hChild<span style="color: #339933;">,</span> GW_HWNDLAST<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #808080; font-style: italic;">/* ... */</span><br />
&nbsp; hTemp <span style="color: #339933;">=</span> GetWindow<span style="color: #009900;">&#40;</span>hChild<span style="color: #339933;">,</span> GW_HWNDNEXT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Pomysł <strong>zły</strong> ! Okazuje się że taka pętla może działać w nieskończoność. Wzmianaka na temat takiego przypadku znajduje się nawet w dokumentacji. Dlatego należy wykorzystać inny sposób, polegający na użyciu funkcji <code>BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)</code>:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">EnumWindows<span style="color: #009900;">&#40;</span>EnumWindowsProc<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #808080; font-style: italic;">/* ... */</span><br />
BOOL CALLBACK EnumWindowsProc<span style="color: #009900;">&#40;</span>HWND hwndChild<span style="color: #339933;">,</span> LPARAM lParam<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #993333;">char</span> buffer<span style="color: #009900;">&#91;</span>100<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #993333;">int</span> count <span style="color: #339933;">=</span> GetWindowText<span style="color: #009900;">&#40;</span>hwndChild<span style="color: #339933;">,</span> buffer<span style="color: #339933;">,</span> 100<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>count <span style="color: #339933;">&amp;&amp;</span> IsWindowVisible<span style="color: #009900;">&#40;</span>hwndChild<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* ... */</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #b1b100;">return</span> TRUE<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p><strong>2. Nadać oknom styl <code>dwExStyle</code></strong><br />
Wydaje się najtrudniejsze, przecież dodatkowy styl należy podać przy tworzeniu okna, a okna które widzimy zostały już przecież utworzone. Na szczęście z pomocą przychodzi funkcja <code>LONG SetWindowLong(HWND hWnd, int iIndex, LONG dwNewLong)</code>:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SetWindowLong<span style="color: #009900;">&#40;</span>hwndChild<span style="color: #339933;">,</span> GWL_EXSTYLE<span style="color: #339933;">,</span> WS_EX_LAYERED<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p><strong>3. Zmienić wartość kanału alpha</strong><br />
Bardziej uważni czytelnicy już na pewno wiedzą jak wygląda zestaw parametrów i jak skorzystać z <code>SetLayeredWindowAttributes</code>. Wykorzystanie pokazane 3 listingi wyżej, przy okazji tworzenia &#8222;własnego&#8221; przezroczystego okna.</p>
<p>I to tyle  tym temacie, wypada jeszcze stworzyć GUI, może obsługę tray&#8217;a. Program wydaje się &#8222;magiczny&#8221; a korzysta raptem z 4 funkcji API systemowego.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Magiczne delete []</title>
		<link>http://piotr.doniec.eu/devlog/2009/06/magiczne-delete/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/06/magiczne-delete/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 18:09:35 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=209</guid>
		<description><![CDATA[Prawdopodobnie nikt się nie zastanawiał jak dokładnie działa delete [], wystarczy wiedzieć że usuwa wszystkie obiekty umieszczone w dynamicznie zaalokowanej tablicy. Jeżeli obiekty posiadają destruktor to jest on uruchamiany, a jeśli nie to pamięć jest po prostu zwalniana. Muszę przyznać że mnie samemu też nigdy nie przyszło na myśl że może się tam kryć coś]]></description>
			<content:encoded><![CDATA[<p>Prawdopodobnie nikt się nie zastanawiał jak dokładnie działa <code>delete []</code>, wystarczy wiedzieć że usuwa wszystkie obiekty umieszczone w dynamicznie zaalokowanej tablicy. Jeżeli obiekty posiadają destruktor to jest on uruchamiany, a jeśli nie to pamięć jest po prostu zwalniana. Muszę przyznać że mnie samemu też nigdy nie przyszło na myśl że może się tam kryć coś &#8222;magicznego&#8221;. Trawało to do czasu aż zupełnie przypadkiem trafiłem na wpis na blogu który opisuje SKĄD DELETE [] WIE ILE OBIEKTÓW NALEŻY USUNĄĆ.<br />
Nie będę kopiował cudzego wpisy/odkrycia jedynie po przetłumaczeniu na język ojczysty więc odsyłam do źródła oraz zachęcam do lektury (tytuł dodatkowo mówi sam za siebie): <a href="http://mdzahidh.wordpress.com/2007/08/24/a-little-cc-recipe-you-can-live-without-knowing/">http://mdzahidh.wordpress.com/2007/08/24/a-little-cc-recipe-you-can-live-without-knowing/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/06/magiczne-delete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Z C++ zagadka nr 3</title>
		<link>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-3/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-3/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 23:40:33 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=197</guid>
		<description><![CDATA[Kompilator zrobi dokładnie to co chcesz. DOKŁADNIE! i właśnie dlatego trzeba uważać. Ta zagadka jak i pozostałe ma na celu zwrócenie uwagi na miejsca które wydają się oczywiste a moga wprowadzić wiele zamieszania i niepotrzebnych nerwów. W końcu nie od dziś wiadomo że najgroźniejsze błędy znajdują się w &#8222;kodzie który napewno jest dobrze&#8221;. Tym razem]]></description>
			<content:encoded><![CDATA[<blockquote><p>Kompilator zrobi dokładnie to co chcesz. DOKŁADNIE!</p></blockquote>
<p> i właśnie dlatego trzeba uważać. Ta zagadka jak i pozostałe ma na celu zwrócenie uwagi na miejsca które wydają się oczywiste a moga wprowadzić wiele zamieszania i niepotrzebnych nerwów. W końcu nie od dziś wiadomo że najgroźniejsze błędy znajdują się w &#8222;kodzie który napewno jest dobrze&#8221;. Tym razem zagadka wymaga trochę więcej od czytelnika, nie wystarczy znajmość C++, trzeba się jeszcze wykazać odrobiną znajomości biblioteki boost. <span id="more-197"></span><br />
Na problem oczywiście musiałem trafić na klika godzin przed oddaniem projektu, była godzina 5:14 i nie trudno zgadnąć że odchodził istny eXtreme programming &#8211; programowanie gry sieciowej &#8211; 2 osoby &#8211; 24h. Dojście do tego co jest źle zajęło dobrą godzinę&#8230;<br />
Poniższy kod przdstawia 4 najprostsze możliwe przypadki użycia boost::bind w połączeniu z boost::signal, nie różnią się między sobą bardzo:</p>
<pre class="brush: cpp">
#include &lt;boost/signal.hpp&gt;
#include &lt;boost/bind.hpp&gt;

#include &lt;iostream&gt;	

class Test
{
public:
  Test(int x) : x_(x)
  {}

  void metoda1(int i);

  int x_;
};

void Test::metoda1(int i)
{
  x_ += i;
}

int main()
{
  typedef boost::signal&lt;void (int)&gt; event_sig;
  event_sig signal;

  Test* t1 = new Test(0);
  Test* t2 = new Test(0);
  Test t3(0);
  Test t4(0);

  signal.connect(boost::bind(&amp;Test::metoda1, *t1, _1));
  signal.connect(boost::bind(&amp;Test::metoda1,  t2, _1));
  signal.connect(boost::bind(&amp;Test::metoda1, &amp;t3, _1));
  signal.connect(boost::bind(&amp;Test::metoda1,  t4, _1));

  for(int i = 0; i &lt; 10; ++i)
  {
    signal(1);
  }

  std::cout &lt;&lt; &quot;t1::x = &quot; &lt;&lt; t1-&gt;x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;t2::x = &quot; &lt;&lt; t2-&gt;x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;t3::x = &quot; &lt;&lt; t3.x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;t4::x = &quot; &lt;&lt; t4.x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;Powinno(?) byc 10&quot; &lt;&lt; std::endl;
}
</pre>
<p>Mogło by się wydawać że w wyniku, na ekran zostanie wypisana 4 razy liczba 10. Ci bardziej podejrzliwi zaczną się zastanawiać, jaki wpływ mogą mieć te &#8222;dodatkowe&#8221; symbole dostawione wewnątrz boost::bind. Okazuje się że w przypadkach 1 i 4 ( t1 i t4 ), mimo wysyłania sygnału, wartość pola x_ nie ulega zmianie, natomiast w pozostałych ulega. Dlaczego ?<br />
Rozwiązanie tego problemu jest bardo proste, otóż tworząc binda, biblioteka boost w zależności od sposobu przekazania obiektu na rzecz którego zostanie wywołana metoda, utworzy jego kopię (internal copy) lub będzie operować na przekazanym obiekcie.<br />
Niby proste, ale trzeba mieć świadomość o istnieniu takiego mechanizmu. Nie trudno się &#8222;przejechać&#8221; na złym przekazaniu obiektu, a tu nie będzie sugestywnego &#8222;segmentation fault&#8221;&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Z C++ zagadka nr 2</title>
		<link>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-2/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-2/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 11:49:26 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=188</guid>
		<description><![CDATA[Zagadka nr 2 bardzo blisko związana z zawiłościami języka programowania c++, choć okazuje się że dotyczy także innych, w tym np. Javy. Kod wydaje się banalnie prosty. Jednak jak mówi &#8222;stare chińskie przysłowie&#8221;  &#8211; &#8222;Diabeł tkwi w szczegółach&#8221;. Czego można by się spodziewać po wykonaniu takiego kodu ? #include &#60;iostream&#62; int main() { for(double i]]></description>
			<content:encoded><![CDATA[<p>Zagadka nr 2 bardzo blisko związana z zawiłościami języka programowania c++, choć okazuje się że dotyczy także innych, w tym np. Javy. Kod wydaje się banalnie prosty. Jednak jak mówi &#8222;stare chińskie przysłowie&#8221;  &#8211; &#8222;Diabeł tkwi w szczegółach&#8221;.<br />
<span id="more-188"></span><br />
Czego można by się spodziewać po wykonaniu takiego kodu ?</p>
<pre class="brush: cpp">
#include &lt;iostream&gt;

int main()
{
    for(double i = 0; i != 1; i+= 0.1)
    {
        std::cout &lt;&lt; &quot;Obrot petli i = &quot; &lt;&lt; i &lt;&lt; std::endl;
    }
}
</pre>
<p>Odpowiedź na to pytania wymaga trochę więcej niż tylko znajomości składni języka. Na pierwszy rzut oka wydawać się może że pętla dokona 10 obrotów a następnie program się skończy. Gdyby to był 1 kwietnia wiele osób uznało by za żart stwierdzenie że pętla będzie działać w nieskończoność, choć tak naprawdę jest !! Program nie zauważy że dobił do 1 i powinien przestać działać. Co więcej, na ekran zostanie wypisana liczba 1 a mimo to działanie nie zostanie przerwane. Wyjaśnienia tego przypadku, trzeba szukać w komputerowej reprezentacji liczby 0.1 <img src='http://piotr.doniec.eu/devlog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Funkcje wirtualne w c++</title>
		<link>http://piotr.doniec.eu/devlog/2009/05/funkcje-wirtualne-w-c/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/05/funkcje-wirtualne-w-c/#comments</comments>
		<pubDate>Fri, 15 May 2009 14:26:11 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[wirtualność]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=179</guid>
		<description><![CDATA[Mechanizm funkcji wirtualnych, występujący także pod nazwą &#8222;późnego wiązania&#8221;, jest bardzo ważny elementem języka programowania. Pozwala na wywołania innej wersji metody w zależności od obiektu na rzecz którego metoda jest wywoływana.  Największe zastosowanie funkcji wirtualnych to umożliwienie przechowywanie obiektów w kolekcjach jako obiektów klasy bazowej, a wywoływanie metod które dotyczą faktycznego typu obiektu. O ile]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Mechanizm funkcji wirtualnych, występujący także pod nazwą &#8222;późnego wiązania&#8221;, jest bardzo ważny elementem języka programowania. Pozwala na wywołania innej wersji metody w zależności od obiektu na rzecz którego metoda jest wywoływana.  Największe zastosowanie funkcji wirtualnych to umożliwienie przechowywanie obiektów w kolekcjach jako obiektów klasy bazowej, a wywoływanie metod które dotyczą faktycznego typu obiektu.<span id="more-179"></span><br />
O ile w przypadku funkcji niewirtualnych kompilator nie ma problemu z obliczeniem adresu funkcji w czasie kompilacji i konsolidacji, a wywołanie odnosi się do obliczonego statycznego adresu.<br />
W przypadku funkcji wirtualnych sprawa wygląda trochę inaczej, ponieważ funkcja którą należy wywołać zależy również od typu obiektu na rzecz którego następuje próba wywołania. Dlatego kompilator tworzy sobie dla każdej klasy tabelę wywołań funkcji wirtualnych v-table. Tabela jest tworzona 1 dla jednej klasy i jest wspólna dla wszystkich obiektów danej klasy. Tabela v-table jest tworzona tylko wtedy gdy została zadeklarowana przynajmniej jedna funkcja wirtualna. Każda klasa ma wskaźnik na tabelę funkcji wirtualnych z której korzysta kiedy ma wywołać metodę która została zadeklarowana jako wirtualna. Wskaźnik tablicy wirtualnej jest zazwyczaj pierwszym elementem obiektu. Wynikający z istnienia vtable narzut pamięciowy jest raczej skromny. Rozmiar obiektu rośnie o wielkość samego wskaźnika, czyli o 4KB a zapotrzebowanie całego programu jest wprost proporcjonalne do ilości funkcji wirtualnych.<br />
<img class="size-full wp-image-180 alignnone" title="ovp-fig6" src="http://piotr.doniec.eu/devlog/wp-content/uploads/2009/05/ovp-fig6.gif" alt="ovp-fig6" width="314" height="314" /></p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/05/funkcje-wirtualne-w-c/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Z C++ zagadka</title>
		<link>http://piotr.doniec.eu/devlog/2009/03/z-c-zagadka/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/03/z-c-zagadka/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 10:29:17 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[wirtualność]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=132</guid>
		<description><![CDATA[Na ostatnich inżynierskich targach pracy i praktytk trafiłem na dość trudny test z C++. Pojawiło się na nim zadanie co do którego miałem wątpliwości szczególnie że sprawdzający stwierdził że nie mam racji. Treść zapamiętałem i postanowiłem sprawdzić nie teoretycznie na kartce, ale po prostu jak się zachowa prawdziwy kompilator. Treść jest bardzo prosta, jaki będzie]]></description>
			<content:encoded><![CDATA[<p>Na ostatnich inżynierskich targach pracy i praktytk trafiłem na dość trudny test z C++. Pojawiło się na nim zadanie co do którego miałem wątpliwości szczególnie że sprawdzający stwierdził że nie mam racji. Treść zapamiętałem i postanowiłem sprawdzić nie teoretycznie na kartce, ale po prostu jak się zachowa prawdziwy kompilator. <span id="more-132"></span>Treść jest bardzo prosta, jaki będzie efekt kompilacji i uruchomienia poniższego kodu:</p>
<pre class="brush: cpp">
class A
{
public:
  A() {
    fun();
  }

  virtual void fun()  {
    std::cout &lt;&lt; &quot;A::fun&quot; &lt;&lt; std::endl;
  }

  void fun2()  {
    fun();
  }
};

class B : public A
{
  void fun()  {
    std::cout &lt;&lt; &quot;B::fun&quot; &lt;&lt; std::endl;
  }
};

int main() {
  A* a = new B();
}
</pre>
<p>Poprawna odpowiedź:<br />
<code>A::fun</code><br />
dlaczego? W konstruktorze nie działa wirtualność. Zatem to ja miałem racje !<br />
Za to gdyby dopisać jeszcze </p>
<pre class="brush: cpp">
a-&gt;fun2();
</pre>
<p>to byśmy zobaczyli już <code>B::fun</code>. Problem zapewne rzadko w praktyce występuje ale jest to genialne zadanie na wszelkiej maści testy mające sprawdzić zaawansowaną znajomość mechanizmów języka C++</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/03/z-c-zagadka/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
