Otázky a odpovědi

V této části budou zveřejněny vaše dotazy i s naší odpovědí. Tak si budou moci odpověď přečíst všichni zájemci a ne pouze tazatel. Dotazy ke Kurzu C/C++ posílejte na email mého kolegy: mrandrew@atlas.cz a dotazy ke kurzu o DirectX posílejte na můj email: jiri.formanek@centrum.cz.

Pro větší přehlednost jsem rozdělil tuto sekci do více částí:

Obecné otázky
Dotazy k C++
Dotazy k DirectX
Krátké příklady


Obecné otázky týkající se programování

Je lepší Microsoft Visual C++ nebo Borland C++?
Osobně bych Vám doporučoval Visual C++, ale je to také věc vkusu. Pokud nemáte nic proti Microsoftu tak jděte do Visual C++, v opačném případě do Borlandu, který sice není špatný, ale podle mého názoru se VC++ nevyrovná. Microsoft má určitě lepší podporu nebo spíš reklamu:)

Poznámka k publikování článku mimo ChipCD.
Články jsou publikovány s přibližně tří měsíčním zpožděním na serveru casopis.programator.cz. Články na tomto serveru mohou být ochuzeny o příklady a některé obrázky.

Lze změnit nastavení již rozpracovaného projektu na statické linkovaní MFC, aniž bych musel projekt znovu zavádět?
Samozřejmě. V menu Project zvolte položku Settings. Tam hned na první kartě najdete způsob linkovaní. Dávejte si ale pozor na to, že konfigurace projektu je rozdělena pro Release a Debug režim. Musíte ji nastavit nejlépe pro oba režimy, ale hlavně pro Release, protože tuto verzi pak distribuujete.

Mám nějakou třídu (například CMujEdit zděděný od CEdit) a mám ji zobrazenu v panelu ClassView. Občas se stane následující věc, které nerozumím: přidám třídě pomocí položky kontextoveho menu "Add Windows Message Handler" nějakou oblužnou funkci, pak se mi nelíbí co dělá a já ji chci odstranit. Pokud ji smažu ručně přímo v kódu, stejně jako odkaz na ní v mapě zpráv a v hlavičkovém souboru, je vše v pořádku. Pokud však kliknu v ClassView u příslušné metody na Delete a potvrdím, že se mají odkazy smazat a tělo metody zakomentovat, pak se někdy stane, že mi celá třída zmizí z ClassView a zpět se mi objeví teprve poté, co pomoci ClassWizardu znovu přidám smazanou metodu. Když ji následně vymažu "ručně", je vše v pořádku. Čím to je způsobeno?
ClassView není dokonalé. Pokud vymažete kousek klíčového slova "class", tak třída z ClassView zmizí a to je v pořádku, protože vývojové prostředí tuto třídu nenajde, ale občas se stane, že třída zmizí při normalní operaci s třídou jako je například přidávání a mazání funkcí. Toto je chyba samotného vývojového prostředí a ani nejnovější SP (Service Pack) tuto chybu neopravuje. Pokud se vám stane, že třída zmizí, pokuste se vratit krok, po kterém třída zmizela a posléze ho proveďte znovu. Pokud nejde krok vrátit, musíte buďto čekat až se jednoho krásneho dne třída znovu objeví nebo by mělo stačit vyjmout a zase přidat hlavičkový i implementační soubor, ve kterém je třída. Zkuste restartovat VC++ i cely počítač a poslední možnost je, že vymažete soubory s příponami .ncb a .opt v adresáři vašeho projektu. To jsou soubory, ve kterých je uložena právě struktura ClassView a vy tak přinutíte VC++, aby ji znovu vytvořilo.

Existuje nějaké freeware vývojové prostředí pro jazyk C/C++ a kde jej mohu získat?
Ano, existuje Dev-C++ a stáhnout si ho můžete na této adrese: www.bloodshed.nu. Nové Dev-C++ by mělo být k dispozici na ChipCD.


Dotazy k C++

Jaký je rozdíl mezi cout a printf()?
Ve VC++ je možné používat obojí, cout i printf(). Osobně mám radši printf(), protože umožňuje lepší formátování – kratší a přehlednější, ale jinak je to zcela na Vás.

Mohl byste mi vysvětlit rozdíl mezi ukazatelem a normální proměnnou? Proč některé funkce chtějí jako parametry ukazatele a jiné normální proměnnou?
Všimněte si, že např. funkce SelectObject() bere jako parametr ukazatel na objekt. Když se funkci předává parametr hodnotou (to znamená jako normální proměnnou bez hvězdičky), udělá se kopie předávaného objektu na stacku. Když se jedná o objekt, musí se udělat kompletní kopie, všechny proměnné! Představte si, že objekt bude mít 20 proměnných a navíc může obsahovat další objekty – to jistě uznáte, že je značně neefektivní, když pak tuto kopii stejně zahodíte. Mnohem lepší je, když předáte pouze ukazatel. Takže obecně platí, že když předáváte objekty je lepší používat ukazatele, i když nechcete objekt uvnitř funkce měnit. Naopak u běžných typů se předává hodnota, samozřejmě pokud chcete hodnotu proměnné ve funkci měnit, musíte předat buď ukazatel nebo referenci.

Je lepší Java nebo C++, a v čem?
Nedá se říci, jestli je lepší Java nebo C++. Za prvé, každý jazyk má své přednosti a své nevýhody. Za druhé se jedná o dva různé typy programovacích jazyků. I když je syntaxe velice podobná, C++ je jazyk kompilovaný tzn. že program se jednou přeloží a pak už se jen spouští. Ale Java je jazyk interpretovaný tzn. že se kód překládá při každém spuštění. Proto také C++ nemá svůj skriptovací jazyk (známe JavaScript, VBScript, ale C++Script nikoliv:). Takže by se dalo říci, že program v C++ bude vždy rychlejší než stejný program v Javě, ale také to záleží na mnoha dalších okolnostech.

Používá se v C++ v deklaraci proměnné slovo var, co to var znamená?
Nepoužívá. Klíčové slovo var se používá v Pascalu k deklaraci proměnných a k předávání parametrů funkcím odkazem. Jinak var je zřejmě od slova variable, což je proměnná.

Na základě vašeho kurzu jsem se začal učit programovací jazyk C, za použití knihy "Učebnice jazyka C 1.". Mám však problém: vždy když zkompiluji svůj program, ten se zpustí,ale po provedení všech příkazů se ihned ukončí a já nejsem schopen zkontrolovat správnost výpočtů na obrazovce. Po zkušenostech s Pascalem jsem hledal v knize nějaký příkaz podobný READKEY, ale nic takového jsem nenašel. Má jazyk C nějaký podobný příkaz? Nebo je chyba v mém kompileru?
Chyba to není. Program prostě skončí a výstupní okno se zavře. Pokud je výpočet programu rychlý, člověk postřehne jen probliknutí. Úplný ekvivalent funkci READKEY z Pascalu v C nenajdete, ale můžete použít funkci getchar(), která funguje podobně (navíc vrací ordinální číslo stisknutého znaku). Abyste mohli tuto funkci použít, musíte vložit hlavičkový soubor stdio.h.

Bude plynulý přechod z C++ na C#?
Snad ano. C# má být něco mezi Visual Basicem a Visual C++, takže prostředí bude zřejmě "přátelštější", ale stále se bude používat jazyk C++. Nyní s odstupem času můžu tento dotaz doplnit. O C# se říká, že je spojením toho nejlepšího z jazyků C++, Visual Basic a Java. Skutečně, když se podíváte na syntaxi, tak je velice podobná Javě a přesto nejde o interpretovaný jazyk. C# je zcela objektově orientovaný jazyk určený pro novou platformu .NET. Pro toho, kdo se učí C++ bude přechod na C# velice rychlý.


Dotazy k DirectX

Co je to sprite?
Odpověď byste jistě našli v některém kurzu DirectX. Sprite je z anglického překladu něco jako duch:-) Sprite je vlastně  vykreslovaný obrázek. Sprite je většinou vytvořen z bitmapy, kterou načtete z externího souboru. Pokud budete mít pohybující se letadlo, právě letadlo bude sprite. Za sprite můžeme považovat například tlačítko menu nebo kurzor myši.

Jak zakomponovat zvuk do stávajících projektu DirectX?
Asi nejlepším řešením je použít další komponentu DirectX a tou je DirectMusic. Tato komponenta umožňuje, jak přehrávání hudby, tak i samostatných zvuků. DirectMusic částečně nahrazuje komponentu DirectSound, který je rovněž k dispozici, ale řekl bych, že s DirectMusic se lépe pracuje. Mám v plánu udělat malý kurz DirectMusic, kde vysvětlím základy, abyste mohli svou aplikaci ozvučit. Nebude to ovšem nic podrobného.V příštím díle DirectX se budu tomuto tématu věnovat.

Poznámka k jiným verzím Visual C++ a DirectX SDK.
Praktickým zkoušením jsem zjistil, že s novým DX SDK 8.0 pracuje pouze Visual C++ 6.0 a vyšší. Na nižších verzích nelze projekty z kurzů zkompilovat kvůli zřejmé nekompatibilitě. Proto pokud vlastníte verzi 4.0 nebo 5.0 nemůžete používat DirectX 8.0. DirectX SDK 8.0 vyšlo na ChipCD vydání 11/01.

Existuje česky psaná kniha o DirectX?
Bohužel jsem o takové publikaci neslyšel. V angličtině je takových knih několik (viz. www.microsoft.com).

Bude nejaky seriál o DirectShow?
Nebude. Po DirectDraw bych chtěl pokračovat komponentou DirectInput a pak ještě nevím, ale DirectShow to nebude.


Krátké příklady

2. Nevíte, jak se dá v C++ vytvořit dynamicky alokované pole ukazatelů na int?

Víme. Stačí použít pointer na pointer na integer. Nejprve vytvoříte pole ukazatelů na integer, potom přes ukazatele v tomto poli vytvořite pole integeru. Srozumitelnější bude spíš ukázka:

#include "stdafx.h"
#include <stdio.h>

int **pp_pole;
typedef int *PINT; 

int main(int argc, char* argv[])
{
    pp_pole = NULL;
    pp_pole = new PINT[10]; 

    pp_pole[0] = new int[1];
    pp_pole[1] = new int[2];
    pp_pole[2] = new int[4];

    pp_pole[0][0] = 5;
    pp_pole[1][0] = 6;
    pp_pole[1][1] = 7;
    pp_pole[2][0] = 8;
    // atd. 
    printf("V poli jsou:\n%u\n%u %u\n", pp_pole[0][0], pp_pole[1][0], pp_pole[1][1]);

    return 0;
}

 

1. Program pro převod čísla z desítkové soustavy do binární

1. Trocha teorie

Vezmeme desítkové číslo a stále ho celočíselně dělíme dvěma, zbytek po tomto dělení sepíšete a pak odspoda přečtete číslo vyjádřené ve dvojkové soustavě. Tedy například pro 157:

Operace Výsledek Zbytek
157 : 2 78 1
78 : 2 39 0
39 : 2 19 1
19 : 2 9 1
9 : 2 4 1
4 : 2 2 0
2 : 2 1 0
1 : 2 0 1

A přečteme zespoda. Tedy: (157)dec = (10011101)bin.

2. Praxe

Proměnné:

length je délka binárního čísla, můžete ale zvolit pevně.
retezec je již alokované pole znaku o dostatečné velikosti (max. počet znaku bin. čísla + 1 znak na ukončovací \0) dělíme bitovým posunem, kdy prostě zahodíme nejméně významný bit a tím se číslo vydělí dvěma. Výsledný řetězec je vytvářen od konce.

Vlastní program:

if(0 == cislo) // osetrime 0
{
    retezec[length - 2] = '0';
}
else
{
    short index = length-1;
    while(cislo > 1)
    {
        retezec[--index] = (char)('0' + (cislo % 2));
// zbytek dame do spravne pozice
        cislo >>= 1;
// vydelime dvema (bitovy posun)
    }
    retezec[--index] = '1';
}