C++ návod pro uživatele C

Tento text přehlídky a zvýrazní rysy a základní principy C++. Je zaměřena na zkušené uživatele C kteří se chtějí naučit C++. Budete mít možnost vyjádřit svůj kód pomocí bohatší C++ syntaxi a budete moci přečíst nějaké C++ kódu.

Přestože se koncept je představen a udělal použitelné, to není výukový program o objektově orientovaného programování. Stále budete muset naučit ducha OOP a podrobnosti jeho implementace v C++, aby byl pravdivý C++ programátor.

Pokud nemáte C++ kompilátor po ruce, možná zkusit použít online nástroje jako je tento: http://codepad.org


1. Nový způsob, jak zahrnout knihovny

2. // pro jeden řádek poznámky

3. Vstupní konzola a výstupní proudy

4. Deklarace proměnných lze dát dovnitř kódu bez použití háků

5. Proměnné lze inicializovat výpočtem se jedná o jiné proměnné

6. Proměnné mohou být deklarovány uvnitř bloku for prohlášení smyčky

7. Globální proměnné lze přistupovat iv případě, že lokální proměnné mají stejný název

8. Je možné deklarovat ODKAZEM na jiné proměnné

9. Jmenné prostory mohou být deklarovány

10. Funkce může být prohlášena za inline

11. Struktura výjimka byla přidána

12. Funkce může mít výchozí parametry

13. FUNKCE PŘETÍŽENÍ: několik funkce mohou být deklarovány se stejným názvem předpokladu, že existuje rozdíl v jejich seznamu parametrů

14. Symbolické operátory (+ - * / ...) lze definovat pro nové datové typy

15. Různé funkce pro různé typy dat se generuje automaticky znáte-li definovat funkci template

16. Klíčová slova new a delete jsou mnohem lepší přidělit a deallocate paměť

17. Můžete přidat METODY, aby class nebo struct

18. KONSTRUKTOR a DESTRUKTOR mohou být použity k inicializaci a zničit instance třídy

19. Komplexní třídy potřebují KOPIE KONSTRUKTOR a přetížení = operátora

20. Metoda tělesa lze definovat pod definici třídy (a Makefile příklad použití)

21. Klíčové slovo this je ukazatel na instanci metoda je působícím na

22. Pole instancí může být prohlášen

23. Příkladem úplného prohlášení třídní

24. static proměnné uvnitř definice třídy

25. const proměnné uvnitř definice třídy

26. Třída může být ODVOZENA z jiné třídy

27. Je-li metoda deklarována virtual program bude vždy zkontrolovat typ instance, která je zaměřena na a bude používat vhodnou metodu.

28. Třída může být odvozena od více než jedné základní třídy

29. Třída odvození vám umožní psát obecné metody

30. ZAPOUZDŘENÍ: public, protected a private.

31. Stručné příklady I/O souboru

32. Znakové sady mohou být použity jako soubory

33. Příkladem formátovaný výstup


1.

K dispozici je nový způsob, jak #include knihoven (stará metoda stále funguje ještě kompilátor stěžuje). .h Prodloužení se nepoužívá, a jména standardních knihoven C jsou psány začínající C. Aby program používat tyto knihovny správně using namespace std; Je třeba dodat:

using namespace std;
#include <iostream> // To je klíčový knihovna C++
#include < cmath> // Standardní C knihovna math.h

int main ()
{
double a;

a = 1.2;
a = sin (a);

cout << a << endl;

return 0;
}

Output
0.932039

Několik rad pro začátečníky:

Zkompilovat tento program, zadejte jej (nebo zkopírovat a vložit jej) do textového editoru (gedit, kwrite, kate, kedit, vi, emacs, nano, pico, mcedit, Notepad...), uložit jej jako soubor s názvem, říkají test01.cpp (pokud jste nováček, nejlepší umístit tento soubor ve vašem domovském adresáři, který je například /home/jones na Unix-jako box).

Sestavit soubor zdrojový kód, zadejte tento příkaz (na většině open-source Unix-like boxy) v konzoli nebo terminálovém okně:

g++ test01.cpp -o test01

Pro spuštění binární spustitelný soubor test01  která byla vypracována kompilace (za předpokladu, že nedošlo k chybám), napište toto:

./test01

Pokaždé, když změníte zdrojový soubor test01.cpp kód, musíte jej znovu sestavit, pokud chcete, aby se změny odrazí v test01 spustitelného souboru (zadejte šipky nahoru na klávesnici vyvolat příkazy).


2.

Můžete použít // psát poznámku:

using namespace std;         // Použití standardní knihovny názvů.
#include <iostream> // Knihovna iostream je často používán.

int main () // Hlavní rutina programu.
{
double a; // Deklarace proměnné a.

a = 456.47;
a = a + a * 21.5 / 100; // Výpočet.

cout << a << endl; // Zobrazit obsah a.

return 0; // Konec programu.
}

Output
554.611

(Možnost použití // psát poznámky byla přidána k C v C99 a ANSI C 2000.)


3.

Vstup z klávesnice a výstup na obrazovce mohou být prováděny pomocí cout << a cin >>:

using namespace std;
#include <iostream>

int main()
{
int a; // a je celé číslo proměnná
char s [100]; // s body na řetězec maximálně 99 znaků

cout << "This is a sample program." << endl;

cout << endl; // Jen line feed (konec řádku)

cout << "Type your age : ";
cin >> a;

cout << "Type your name: ";
cin >> s;

cout << endl;

cout << "Hello " << s << " you're " << a << " old." << endl;
cout << endl << endl << "Bye!" << endl;

return 0;
}

Output
This is a sample program.

Type your age : 12
Type your name: Edmond       

Hello Edmond you're 12 old.


Bye!

4.

Proměnné mohou být deklarovány kdekoliv uvnitř kódu:

using namespace std;
#include <iostream>

int main ()
{
double a;

cout << "Hello, this is a test program." << endl;

cout << "Type parameter a: ";
cin >> a;

a = (a + 1) / 2;

double c;

c = a * 5 + 1;

cout << "c contains  : " << c << endl;

int i, j;

i = 0;
j = i + 1;

cout << "j contains  : " << j << endl;

return 0;
}

Output
Hello, this is a test program.
Type parameter a: 7
c contains      : 21
j contains      : 1

Možná, že se snaží využívat tuto funkci, aby se váš zdrojový kód čitelnější a nikoli na to bordel až.

Stejně jako v C, proměnné mohou být zapouzdřena mezi { } bloky. Pak jsou místní v rozsahu do zóny zapouzdřeného mezi { a }. Cokoliv se stane s těmito proměnnými uvnitř zapouzdřeného zóny nebude mít žádný efekt mimo zóny:

using namespace std;
#include <iostream>

int main ()
{
double a;

cout << "Type a number: ";
cin >> a;

{
int a = 1;
a = a * 10 + 4;
cout << "Local number: " << a << endl;
}

cout << "You typed: " << a << endl;

return 0;
}

Output
Type a number: 9
Local number: 14
You typed: 9


5.

Proměnná může být inicializovat výpočtem se jedná o jiné proměnné:

using namespace std;
#include <iostream>

int main ()
{
double a = 12 * 3.25;
double b = a + 1.112;

cout << "a contains: " << a << endl;
cout << "b contains: " << b << endl;

a = a * 2 + b;

double c = a + b * a;

cout << "c contains: " << c << endl;

return 0;
}

Output
a contains: 39
b contains: 40.112
c contains: 4855.82


6.

C ++ vám umožňuje deklarovat proměnnou být místní smyčky:

using namespace std;
#include <iostream>

int main ()
{
int i; // Jednoduché prohlášení i
i = 487;

for (int i = 0; i < 4; i++) // Lokální deklarace i
{
cout << i << endl; // Tento výstupy 0, 1, 2 a 3
}

cout << i << endl; // Tento výstup 487

return 0;
}

Output
0
1
2
3
487

V případě, že proměnná není deklarována někde nad smyčkou, můžete být v pokušení ji použít pod smyčce. Některé časné C++ kompilátory přijmout. Poté je proměnná má hodnotu, kterou měl, když smyčka skončí. Neměli byste to dělat. To je považováno za špatné praxe:

using namespace std;
#include <iostream>

int main ()
{

for (int i = 0; i < 4; i++)
{
cout << i << endl;
}

cout << i << endl; // Špatná praxe!
i += 5; // Špatná praxe!
cout << i << endl; // Špatná praxe!

return 0;
}

Gnu C++ compiler complain
t.cpp: In function ‘int main()’:
t.cpp:12: error: name lookup of ‘i’ changed for new ISO ‘for’ scoping
t.cpp:7: error:   using obsolete binding at ‘i’


7.

Globální proměnnou lze přistupovat i když jiná proměnná se stejným názvem byla prohlášena uvnitř funkce:

using namespace std;
#include <iostream>

double a = 128;

int main ()
{
double a = 256;

cout << "Local a: " << a << endl;
cout << "Global a: " << ::a << endl;

return 0;
}

Output
Local a:  256
Global a: 128


8.

Je možné, aby se jedna proměnná být jiný:

using namespace std;
#include <iostream>

int main ()
{
double a = 3.1415927;

double &b = a; // b je a

b = 89;

cout << "a contains: " << a << endl; // Zobrazuje 89.

return 0;
}

Output
a contains: 89

(Pokud jste zvyklí na ukazatele a naprosto chtějí vědět, co se děje, prostě přemýšlet double &b = a je přeložen na double *b = &a a všechny následné b jsou nahrazeny *b.)

Hodnota referenčního b nelze změnit po jejím vyhlášení. Například nemůžete psát, pár řádků dále, &b = c očekávají, že b je nyní c. To nebude fungovat. Všechno, co se říká, v prohlášení na řádku b. Referenční b a proměnnou a jsou v ženatý na stejné lince a nic se od sebe oddělit.

Reference může být použita pro umožnění funkce upravit volání proměnné:

using namespace std;
#include <iostream>

void change (double &r, double s)
{
r = 100;
s = 200;
}

int main ()
{
double k, m;

k = 3;
m = 4;

change (k, m);

cout << k << ", " << m << endl; // Zobrazuje 100, 4.

return 0;
}

Output
100, 4

Pokud jste zvyklí na ukazatele v C a divit, jak přesně program výše děl, tady je, jak by ji C++ kompilátor přeložit do C:

using namespace std;
#include <iostream>

void change (double *r, double s)
{
*r = 100;
s = 200;
}

int main ()
{
double k, m;

k = 3;
m = 4;

change (&k, m);

cout << k << ", " << m << endl; // Zobrazuje 100, 4.

return 0;
}

Output
100, 4

Referenční může být použit, aby funkce vrací proměnnou:

using namespace std;
#include <iostream>

double &biggest (double &r, double &s)
{
if (r > s) return r;
else return s;
}

int main ()
{
double k = 3;
double m = 7;

cout << "k: " << k << endl; // Displeje 3
cout << "m: " << m << endl; // Displeje 7
cout << endl;

biggest (k, m) = 10;

cout << "k: " << k << endl; // Displeje 3
cout << "m: " << m << endl; // Displeje 10
cout << endl;

biggest (k, m) ++;

cout << "k: " << k << endl; // Displeje 3
cout << "m: " << m << endl; // Displeje 11
cout << endl;

return 0;
}

Output
k: 3
m: 7

k: 3
m: 10

k: 3
m: 11


Opět platí, že pokud jste zvyklí ukazatel aritmetiku a pokud by vás zajímalo, jak program výše děl, jen si představte, že překladač jej přeložil do následujícího standardního programu C:

using namespace std;
#include <iostream>

double *biggest (double *r, double *s)
{
if (*r > *s) return r;
else return s;
}

int main ()
{
double k = 3;
double m = 7;

cout << "k: " << k << endl;
cout << "m: " << m << endl;
cout << endl;

(*(biggest (&k, &m))) = 10;

cout << "k: " << k << endl;
cout << "m: " << m << endl;
cout << endl;

(*(biggest (&k, &m))) ++;

cout << "k: " << k << endl;
cout << "m: " << m << endl;
cout << endl;

return 0;
}

Output
k: 3
m: 7

k: 3
m: 10

k: 3
m: 11


Skončit, pro lidi, kteří budou muset vypořádat s ukazateli ještě se to nemusí líbit, odkazy jsou užitečné, aby účinně un-ukazatel proměnné. Dejte si pozor na to lze považovat za špatná praxe a mohou se dostat do problémů. Viz například

http://web.archive.org/web/20131011080757/http://www.embedded.com/electronics-blogs/programming-pointers/4023307/References-vs-Pointers

using namespace std;
#include <iostream>

double *silly_function () // Tato funkce vrací ukazatel na double
{
static double r = 342;
return &r;
}

int main ()
{
double *a;

a = silly_function();

double &b = *a; // Nyní b je dvojité vůči níž bodů!

b += 1; // Výborně!
b = b * b; // Není třeba psát *a všude!
b += 4;

cout << "Content of *a, b and r: " << b << endl;

return 0;
}

Output
Content of *a, b and r: 117653


9.

Jmenné prostory mohou být prohlášen. Proměnné deklarované v oboru názvů mohou být použity díky :: provozovatele:

using namespace std;
#include <iostream>
#include <cmath>

namespace first
{
int a;
int b;
}

namespace second
{
double a;
double b;
}

int main ()
{
first::a = 2;
first::b = 5;

second::a = 6.453;
second::b = 4.1e4;

cout << first::a + second::a << endl;
cout << first::b + second::b << endl;

return 0;
}

Output
8.453
41005


10.

Jestliže funkce obsahuje pouze jednoduché řádků kódu, nepoužívá for smyček nebo podobně, může být prohlášena za inline. To znamená, že jeho kód se vloží všude je použita funkce. To je něco jako makro. Hlavní výhodou je tento program bude rychlejší. Malý nevýhodou je, že bude větší, protože byl vložen úplný kód funkce všude tam, kde se používá:

using namespace std;
#include <iostream>
#include <cmath>

inline double hypothenuse (double a, double b)
{
return sqrt (a * a + b * b);
}

int main ()
{
double k = 6, m = 9;

// Další dva řádky vyrobit přesně stejný kód:

cout << hypothenuse (k, m) << endl;
cout << sqrt (k * k + m * m) << endl;

return 0;
}

Output
10.8167
10.8167

(Inline funkce byly přidány do složky C v C99 a ANSI C 2000.)


11.

Víte, klasické řídící struktury C: for, if, do, while, switch...C++ přidává ještě jeden řídící struktura s názvem VÝJIMKA:

using namespace std;
#include <iostream>
#include <cmath>

int main ()
{
int a, b;

cout << "Type a number: ";
cin >> a;
cout << endl;

try
{
if (a > 100) throw 100;
if (a < 10) throw 10;
throw a / 3;
}
catch (int result)
{
cout << "Result is: " << result << endl;
b = result + 1;
}

cout << "b contains: " << b << endl;

cout << endl;

// Dalším příkladem využití výjimky:

char zero [] = "zero";
char pair [] = "pair";
char notprime [] = "not prime";
char prime [] = "prime";

try
{
if (a == 0) throw zero;
if ((a / 2) * 2 == a) throw pair;
for (int i = 3; i <= sqrt (a); i++)
{
if ((a / i) * i == a) throw notprime;
}
throw prime;
}
catch (char *conclusion)
{
cout << "The number you typed is "<< conclusion << endl;
}

cout << endl;

return 0;
}

Output
Type a number: 5

Result is: 10
b contains: 11

The number you typed is prime



12.

Je možné definovat výchozí parametry pro funkce:

using namespace std;
#include <iostream>

double test (double a, double b = 7)
{
return a - b;
}

int main ()
{
cout << test (14, 5) << endl; // Zobrazuje 14 - 5
cout << test (14) << endl; // Zobrazuje 14 - 7

return 0;
}

Output
9
7


13.

Jednou důležitou výhodou C ++ je FUNKCE PŘETÍŽENÍ. Různé funkce mohou mít stejný název, za předpokladu, něco, co umožňuje překladač mezi nimi rozlišovat: počet parametrů, typ parametrů...

using namespace std;
#include <iostream>

double test (double a, double b)
{
return a + b;
}

int test (int a, int b)
{
return a - b;
}

int main ()
{
double m = 7, n = 4;
int k = 5, p = 3;

cout << test(m, n) << " , " << test(k, p) << endl;

return 0;
}

Output
11 , 2


14.

PŘETĚŽOVÁNÍ OPERÁTORŮ lze použít k předefinování základní symbolické operátory pro nové typy parametrů:

using namespace std;
#include <iostream>

struct vector
{
double x;
double y;
};

vector operator * (double a, vector b)
{
vector r;

r.x = a * b.x;
r.y = a * b.y;

return r;
}

int main ()
{
vector k, m; // Není třeba psát "struct vektor"

k.x = 2; // Aby bylo možné psát
k.y = -1; // k = vector (2, -1)
// viz kapitola 19.

m = 3.1415927 * k; // Magie!

cout << "(" << m.x << ", " << m.y << ")" << endl;

return 0;
}

Output
(6.28319, -3.14159)

Kromě násobení, 43 ostatní základní C++ operátory se může přetížit, včetně +=, ++, the array [], a tak dále ...

<< operátor, se běžně používá pro binární posouvání celých čísel, může být přetížen, aby výstup do proudu místo (např., cout <<). Je možné přetížení << operátor dále pro výstup z nové datové typy, jako vektorů:

using namespace std;
#include <iostream>

struct vector
{
double x;
double y;
};

ostream& operator << (ostream& o, vector a)
{
o << "(" << a.x << ", " << a.y << ")";
return o;
}

int main ()
{
vector a;

a.x = 35;
a.y = 23;

cout << a << endl; // Displeje (35, 23)

return 0;
}

Output
(35, 23)


15.

Unavený definování stejnou funkci pětkrát? Jedna z definic pro parametry typu int, jedna definice parametrů typu double, jedna definice pro parametry typu float... Copak jsi zapomněl jeden typ? Co když nový typ dat se používá? Žádný problém: C++ kompilátor dokáže automaticky generovat všechny verze funkce, které jsou nezbytné! Jen to říct, jak tato funkce vypadá tím, že deklaruje template funkci:

using namespace std;
#include <iostream>

template <class ttype>
ttype minimum (ttype a, ttype b)
{
ttype r;

r = a;
if (b < a) r = b;

return r;
}

int main ()
{
int i1, i2, i3;
i1 = 34;
i2 = 6;
i3 = minimum (i1, i2);
cout << "Most little: " << i3 << endl;

double d1, d2, d3;
d1 = 7.9;
d2 = 32.1;
d3 = minimum (d1, d2);
cout << "Most little: " << d3 << endl;

cout << "Most little: " << minimum (d3, 3.5) << endl;

return 0;
}

Output
Most little: 6
Most little: 7.9
Most little: 3.5

Funkce minimum se používá třikrát ve výše uvedeném programu, avšak C++ kompilátor generuje pouze dvě verze je následující: int minimum (int a, int b) a double minimum (double a, double b). Že dělá práci pro celý program.

Co by se stalo, kdyby jste se pokusili něco takového výpočtu minimum (i1, d1)? Kompilátor by hlásili, že jako chybu. To proto, že šablona uvádí, že oba parametry jsou stejného typu.

Můžete použít libovolný počet různých šablon datových typů v definici šablony. A ne všechny typy parametrů musí být šablony, některé z nich mohou být standardních typů nebo uživatelem definované (char, int, double...). Zde je příklad, kdy je minimum funkce trvá parametry jakéhokoliv typu (různé nebo stejný) a dodá hodnotu, která má typ prvního parametru:

using namespace std;
#include <iostream>

template <class type1, class type2>
type1 minimum (type1 a, type2 b)
{
type1 r, b_converted;
r = a;
b_converted = (type1) b;
if (b_converted < a) r = b_converted;
return r;
}

int main ()
{
int i;
double d;

i = 45;
d = 7.41;

cout << "Most little: " << minimum (i, d) << endl;
cout << "Most little: " << minimum (d, i) << endl;
cout << "Most little: " << minimum ('A', i) << endl;

return 0;
}

Output
Most little: 7
Most little: 7.41
Most little: -

(ASCII kód znaku "-" je 45, zatímco kód "A" je 65.)


16.

Klíčová slova new a delete může být použita pro přidělování a deallocate paměti. Jsou čistší než funkcí malloc a free od standardního C.

new [] a delete  [] jsou používány pro pole.

using namespace std;
#include <iostream>
#include <cstring>

int main ()
{
double *d; // d je proměnná, jehož účelem
// musí obsahovat adresu
// zóna, kde se nachází dvojitý


d = new double; // nový přiděluje zónu paměti
// dostatečně velký pro dvojitý
// a vrátí jeho adresu.
// Že adresa je uložena v d.

*d = 45.3; // Číslo 45.3 je uloženo
// uvnitř paměťové zóny
// jehož adresa je dána d.

cout << "Type a number: ";
cin >> *d;

*d = *d + 5;

cout << "Result: " << *d << endl;

delete d; // smazat zruší přidělení se
// zóna paměti, jehož adresa
// je dán ukazatel d.
// Nyní můžeme více používat tuto zónu.


d = new double[15]; // přiděluje zónu pro matici
// 15 zdvojnásobí. Poznámka: každý 15
// dvojitý bude postavena.
// To je zbytečné zde ale
// je velmi důležité při použití datového
// že potřebuje její konstruktér být
// pro každou instanci.

d[0] = 4456;
d[1] = d[0] + 567;

cout << "Content of d[1]: " << d[1] << endl;

delete [] d; // delete [] se navrátit
// paměť zóna. Poznámka: každý 15
// double budou zničeny.
// To je zbytečné zde ale
// je velmi důležité při použití datového typu
// že potřebuje jeho destruktor být
// používá v každém případě, ( ~
// metoda). Používání odstranit, aniž by
// [] by navrátit
// paměť zóna bez destrukci
// každý z instance 15. Že
// by způsobit únik paměti.

int n = 30;

d = new double[n]; // nový lze použít přidělit
// řada náhodné velikosti.
for (int i = 0; i < n; i++)
{
d[i] = i;
}

delete [] d;


char *s;

s = new char[100];

strcpy (s, "Hello!");

cout << s << endl;

delete [] s;

return 0;
}

Output
Type a number: 6
Result: 11
Content of d[1]: 5023
Hello!


17.

Ve standardním C, struct obsahuje pouze data. V jazyce C++, definice struct může také zahrnovat funkce. Tyto funkce jsou vlastnictvím struct a jsou určeny k provozu na datech struct. Tyto funkce jsou tzv METOD. Níže uvedený příklad definuje metodu surface() na struct vector:

using namespace std;
#include <iostream>

struct vector
{
double x;
double y;

double surface ()
{
double s;
s = x * y;
if (s < 0) s = -s;
return s;
}
};

int main ()
{
vector a;

a.x = 3;
a.y = 4;

cout << "The surface of a: " << a.surface() << endl;

return 0;
}

Output
The surface of a: 12

Ve výše uvedeném příkladu, a je INSTANCI struct "vektoru". (Všimněte si, že klíčové slovo "struct" nebylo nutné při deklarování vektor a).

Podobně jako funkce, metoda může být přetížení jakékoliv C++ operátor, mít libovolný počet parametrů (ještě jeden parametr je vždy implicitní: instance působí na), vrátí jakýkoliv typ parametru, nebo se vrátit žádný parametr vůbec.

Co je to class? Je to struct, který udržuje její údaje skryty. Pouze metody class mohou přistupovat k datům. Nelze přistupovat k datům přímo, pokud není povoleno public: směrnice. Zde je příklad class definice. Chová se přesně stejným způsobem jako v příkladu struct výše, protože datové třídní x a y jsou definovány jako veřejnosti:

using namespace std;
#include <iostream>

class vector
{
public:

double x;
double y;

double surface ()
{
double s;
s = x * y;
if (s < 0) s = -s;
return s;
}
};

int main ()
{
vector a;

a.x = 3;
a.y = 4;

cout << "The surface of a: " << a.surface() << endl;

return 0;
}

Output
The surface of a: 12

Ve výše uvedeném příkladu, jehož main() funkcí změní údaje o instance a přímo pomocí a.x = 3 a a.y = 4. To je umožněno tím, public: směrnici v definici třídy. To je považováno za špatné praxe. Viz kapitola 30.

Metoda nemá měnit proměnné instance jedná o:

using namespace std;
#include <iostream>

class vector
{
public:

double x;
double y;

vector its_opposite()
{
vector r;

r.x = -x;
r.y = -y;

return r;
}

void be_opposited()
{
x = -x;
y = -y;
}

void be_calculated (double a, double b, double c, double d)
{
x = a - c;
y = b - d;
}

vector operator * (double a)
{
vector r;

r.x = x * a;
r.y = y * a;

return r;
}
};

int main ()
{
vector a, b;

a.x = 3;
a.y = 5;

b = a.its_opposite();

cout << "Vector a: " << a.x << ", " << a.y << endl;
cout << "Vector b: " << b.x << ", " << b.y << endl;

b.be_opposited();
cout << "Vector b: " << b.x << ", " << b.y << endl;

a.be_calculated (7, 8, 3, 2);
cout << "Vector a: " << a.x << ", " << a.y << endl;

a = b * 2;
cout << "Vector a: " << a.x << ", " << a.y << endl;

a = b.its_opposite() * 2;
cout << "Vector a: " << a.x << ", " << a.y << endl;

cout << "x of opposite of a: " << a.its_opposite().x << endl;

return 0;
}


Output
Vector a: 3, 5
Vector b: -3, -5
Vector b: 3, 5
Vector a: 4, 6
Vector a: 6, 10
Vector a: -6, -10
x of opposite of a: 6

18.

Velmi speciální a základní metody jsou KONSTRUKTORU a DESTRUKTOR. Ty se automaticky svolány, kdykoli je instance třídy je vytvořena nebo zničena (deklarace proměnných, konec programu, new, delete...).

Konstruktor bude inicializovat proměnné instance, udělat nějaké výpočty, alokovat určité množství paměti pro instanci, výstupní některé text ... co je potřeba.

Zde je příklad definice třídy se dvěma přetížené konstruktory:

using namespace std;
#include <iostream>

class vector
{
public:

double x;
double y;

vector () // stejný název jako třída
{
x = 0;
y = 0;
}

vector (double a, double b)
{
x = a;
y = b;
}

};

int main ()
{
vector k; // vector () je nazýván

cout << "vector k: " << k.x << ", " << k.y << endl << endl;

vector m (45, 2); // vector (double, double) je nazýván

cout << "vector m: " << m.x << ", " << m.y << endl << endl;

k = vector (23, 2); // vector vytvořil, zkopírovány do K, poté se termín smaže

cout << "vector k: " << k.x << ", " << k.y << endl << endl;

return 0;
}

Output
vector k: 0, 0

vector m: 45, 2

vector k: 23, 2


Je dobrým zvykem, aby se pokusili nedošlo k přetížení konstruktérů. To je nejlepší vyhlásit pouze jeden konstruktér a dát mu výchozí parametry všude tam, kde je to možné:

using namespace std;
#include <iostream>

class vector
{
public:

double x;
double y;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}
};

int main ()
{
vector k;
cout << "vector k: " << k.x << ", " << k.y << endl << endl;

vector m (45, 2);
cout << "vector m: " << m.x << ", " << m.y << endl << endl;

vector p (3);
cout << "vector p: " << p.x << ", " << p.y << endl << endl;

return 0;
}

Output
vector k: 0, 0

vector m: 45, 2

vector p: 3, 0


Destruktor je často zbytečné. Můžete ji použít k dělat nějaké výpočty, kdykoliv je instance zničen nebo výstup nějaký text pro ladění... Ale pokud proměnné instance poukazují na určité přidělené paměti je tedy zásadní úloha destruktor: musí uvolnit, že paměť! Zde je příklad takové aplikace:

using namespace std;
#include <iostream>
#include <cstring>

class person
{
public:

char *name;
int age;

person (char *n = "no name", int a = 0)
{
name = new char [100]; // lepší než malloc!
strcpy (name, n);
age = a;
cout << "Instance initialized, 100 bytes allocated" << endl;
}

~person () // destruktor
{
delete name; // místo zdarma!

// delete [] název by být více
// akademický, ale to není důležité,
// zde protože pole obsahuje
// žádné C++ sub-objekty, které potřebují
// mají být odstraněny.

cout << "Instance going to be deleted, 100 bytes freed" << endl;
}
};

int main ()
{
cout << "Hello!" << endl << endl;

person a;
cout << a.name << ", age " << a.age << endl << endl;

person b ("John");
cout << b.name << ", age " << b.age << endl << endl;

b.age = 21;
cout << b.name << ", age " << b.age << endl << endl;

person c ("Miki", 45);
cout << c.name << ", age " << c.age << endl << endl;

cout << "Bye!" << endl << endl;

return 0;
}

Output
Hello!

Instance initialized, 100 bytes allocated
no name, age 0

Instance initialized, 100 bytes allocated
John, age 0

John, age 21

Instance initialized, 100 bytes allocated
Miki, age 45

Bye!

Instance going to be deleted, 100 bytes freed
Instance going to be deleted, 100 bytes freed
Instance going to be deleted, 100 bytes freed

Zde je krátký příklad definice jako třída Array. Metoda, která je přetížení operátoru [] a výstupy reference (&) se používá s cílem generovat chybu, pokud je proveden pokus o přístup k datům mimo hranice array:

using namespace std;
#include <iostream>
#include <cstdlib>

class array
{
public:
int size;
double *data;

array (int s)
{
size = s;
data = new double [s];
}

~array ()
{
delete [] data;
}

double &operator [] (int i)
{
if (i < 0 || i >= size)
{
cerr << endl << "Out of bounds" << endl;
exit (EXIT_FAILURE);
}
else return data [i];
}
};

int main ()
{
array t (5);

t[0] = 45; // OK
t[4] = t[0] + 6; // OK
cout << t[4] << endl; // OK

t[10] = 7; // chyba!

return 0;
}


Output
51

Out of bounds

19.

Pokud jste cast objektu jako vektoru, všechno bude dít správně. Například, jestliže vektor k obsahuje  (4, 7), po lité m = k vektor m bude obsahovat (4, 7) i. Hodnoty k.x a k.y byly jednoduše zkopírovány do m.x a m.y. Nyní předpokládejme, že hrajete s objekty, jako jsou třídou person výše. Tyto objekty obsahují ukazatel na řetězec znaků. Pokud jste cast objektu person písemně p = r, že je nezbytné, aby některé funkce dělá práci, aby se p být správná kopie r. V opačném případě p.name bude ukazovat na stejné fyzické řetězce znaků jako r.name. A co víc, bývalý řetězec znaků, na kterou ukazuje se p.name ztracena a stane paměť zombie. Výsledkem bude katastrofální: nepořádek ukazatelů a ztracených dat. Metody, které bude dělat práci, jsou KOPIE KONSTRUKTOR a přetížení = operátora:

using namespace std;
#include <iostream>
#include <cstring>

class person
{
public:

char *name;
int age;

person (char *n = "no name", int a = 0)
{
name = new char[100];
strcpy (name, n);
age = a;
}

person (const person &s) // KOPIE KONSTRUKTOR
{
 name = new char[100];
  strcpy (name, s.name);
 age = s.age;
 }

person& operator= (const person &s) // přetížení =
{
strcpy (name, s.name);
age = s.age;
return *this;
}

~person ()
{
delete [] name;
}
};

void modify_person (person& h)
{
h.age += 7;
}

person compute_person (person h)
{
h.age += 7;
return h;
}


int main ()
{
person p;
cout << p.name << ", age " << p.age << endl << endl;
// výstup: no name, věk 0

person k ("John", 56);
cout << k.name << ", age " << k.age << endl << endl;
// výstup: John, věk 56

p = k;
cout << p.name << ", age " << p.age << endl << endl;
// výstup: John, věk 56

p = person ("Bob", 10);
cout << p.name << ", age " << p.age << endl << endl;
// výstup: Bob, věk 10

// Ani kopie konstruktor ani přetížení
// of = jsou potřebné pro tuto operaci, která upravuje
// p, protože jen odkaz na p je předán
// funkce modify_person:
modify_person (p);
cout << p.name << ", age " << p.age << endl << endl;
// výstup: Bob, věk 17

// Kopie konstruktor je volán projít kompletní
// kopie p do funkce compute_person.
// funkce používá tato kopie, aby své výpočty
// pak kopii tohoto upraveného vyhotovení k tomu,
// vrátit výsledek. Nakonec přetížení = je
// volal vložit tuto druhou kopii uvnitř K:
k = compute_person (p);
cout << p.name << ", age " << p.age << endl << endl;
// výstup: Bob, věk 17
cout << k.name << ", age " << k.age << endl << endl;
// výstup: Bob, věk 24

return 0;
}

Output
no name, age 0

John, age 56

John, age 56

Bob, age 10

Bob, age 17

Bob, age 17

Bob, age 24


Kopírovací konstruktor umožňuje svůj program, aby kopie případech, kdy provádíte výpočty. Je klíčovou metodou. Při výpočtu instance jsou vytvořeny držet průběžných výsledků. Jsou upravené, obsazení a zničeny, aniž byste být si vědom. To je důvod, proč tyto metody mohou být užitečné i pro jednoduché objekty (viz kapitola 14.).

Ve všech výše uvedených příkladech, metody jsou definovány v definici třídy. Že jim automaticky dává vložené metody.

20.

Pokud metoda nemůže být inline, nebo nechcete, aby to bylo inline, nebo chcete-li definice třídy obsahují minimální množství informací (nebo si prostě chcete obvyklý samostatný hlavičkový soubor .h a .cpp zdrojový kód souboru), pak je třeba dát pouze prototyp metody uvnitř třídy a definovat metodu pod třídy (nebo v samostatném zdrojovém souboru .cpp):

using namespace std;
#include <iostream>

class vector
{
public:

double x;
double y;

double surface(); // ; a ne {} ukazují, že je prototyp
};

double vector::surface()
{
double s = 0;

for (double i = 0; i < x; i++)
{
s = s + y;
}

return s;
}

int main ()
{
vector k;

k.x = 4;
k.y = 5;

cout << "Surface: " << k.surface() << endl;

return 0;
}


Output
Surface: 20

Pro začátečníky:

Pokud máte v úmyslu vyvinout vážné C nebo C++ programu, je třeba oddělit zdrojový kód do .h hlavičkové soubory a zdrojové soubory .cpp. Toto je krátký příklad toho, jak se to dělá. Program výše je rozdělen do tří souborů:

Soubor záhlaví vector.h:

class vector
{
public:

double x;
double y;

double surface();
};

Zdrojový soubor vector.cpp:

using namespace std;
#include "vector.h"

double vector::surface()
{
double s = 0;

for (double i = 0; i < x; i++)
{
s = s + y;
}

return s;
}

A další zdrojový soubor main.cpp:

using namespace std;
#include <iostream>
#include "vector.h"

int main ()
{
vector k;

k.x = 4;
k.y = 5;

cout << "Surface: " << k.surface() << endl;

return 0;
}

Za předpokladu, že vector.cpp je perfektní, jej sestavit jednou provždy do .o "objekt souboru". Níže uvedený příkaz vytvoří že strojového kódu soubor s názvem vector.o:

g++ -c vector.cpp

Pokaždé, když změníte zdrojový soubor main.cpp, můžete jej zkompilovat do spustitelného souboru, řekněme test20. Můžete říci kompilátoru výslovně, že má propojit soubor vector.o objekt do závěrečného test20 spustitelný:

g++ main.cpp vector.o -o test20

Spustit spustitelný takto:

./test20

To má několik výhod:

  • Zdrojový kód vector.cpp nemusí být sestaven pouze jednou. To ušetří spoustu času na velkých projektech. (Propojení souboru vector.o do test20  spustitelný soubor je velmi rychlý.)
  • Můžete dát někomu na .h souboru a soubor(y) .o. Tímto způsobem mohou používat svůj software, ale nezmění, protože nemají soubor(y) .cpp (ne příliš spoléhají na to, počkejte, až se zvládnout tyto otázky).

Všimněte si můžete sestavit main.cpp příliš do souboru objektu a poté jej propojit s vector.o:

g++ -c main.cpp
g++ main.o vector.o test20

Tato putuje pryč od "rozdílů mezi C a C++" téma, ale pokud chcete vypadat jako skutečný programátor, musíte kondenzaci výše uvedených příkazů do Makefile a kompilovat pomocí příkaz make. Obsah souboru pod je zjednodušená verze takového Makefile. Zkopírujte jej do souboru s názvem Makefile. Upozorňujeme, a to je velmi důležité, že prostor před g++ příkazů je povinné a že se jedná o charakter Tab. Nezadávejte mezerník zde. Místo toho použijte klávesu sčítací (krajní levé části klávesnice nad Caps Lock).

test20: main.o vector.o
g++ main.o vector.o -o test20

main.o: main.cpp vector.h
g++ -c main.cpp

vector.o: vector.cpp vector.h
g++ -c vector.cpp

Aby bylo možné použít jej Makefile sestavit, typ:

make test20

Příkaz make bude analyzovat pomocí souboru Makefile  a zjistit, co to má co do činění. Pro začátek, je to řečeno, že test20 závisí na main.o a vector.o. Tak to se automaticky spustí "make main.o" a "make vector.o". Pak to bude kontrolovat, jestli test20 již existuje a kontroluje datum razítka test20, main.o a vector.o. Pokud test20 již existuje a main.o a vector.o má datum razítko dříve než test20, příkaz make určí, že aktuální verze test20 je aktuální, takže to nemá nic společného. To bude jen hlásit to neudělal nic. V opačném případě, pokud test20 neexistuje, nebo main.o nebo vector.o jsou novější než test20, příkaz, který vytváří up-to-date verzi test20 je proveden: g++ main.o vector.o -o test20.

Tato nová verze Makefile je blíže ke standardnímu Makefile:

all: test20

test20: main.o vector.o
g++ main.o vector.o -o test20

main.o: main.cpp vector.h
g++ -c main.cpp

vector.o: vector.cpp vector.h
g++ -c vector.cpp

clean:
rm -f *.o test20 *~ #*

Můžete spustit kompilaci pouhým zadáním příkaz make . První řádek v Makefile znamená, že stačí zadat, pokud se budete určen "make test20":

make

Tento příkaz vymaže všechny soubory vznikajících při sestavování a všech textový editor záložních souborů:

make clean

21.

Je-li použita metoda k instanci, může tato metoda použít proměnné instance, upravovat... ale někdy je nutné znát adresu instance. Žádný problém se klíčové slovo this je k tomuto účelu určeny:

using namespace std;
#include <iostream>
#include <cmath>

class vector
{
public:

double x;
double y;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}

double module()
{
return sqrt (x * x + y * y);
}

void set_length (double a = 1)
{
double length;

length = this->module();

x = x / length * a;
y = y / length * a;
}
};

int main ()
{
vector c (3, 5);

cout << "The module of vector c: " << c.module() << endl;

c.set_length(2); // Transformuje c ve vektoru o velikosti 2.

cout << "The module of vector c: " << c.module() << endl;

c.set_length(); // Transformuje b v jednotné vektoru.

cout << "The module of vector c: " << c.module() << endl;

return 0;
}


Output
The module of vector c: 5.83095
The module of vector c: 2
The module of vector c: 1

22.

Samozřejmě, že je možné prohlásit pole objektů:

using namespace std;
#include <iostream>
#include <cmath>

class vector
{
public:

double x;
double y;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}

double module ()
{
return sqrt (x * x + y * y);
}
};

int main ()
{
vector s [1000];

vector t[3] = {vector(4, 5), vector(5, 5), vector(2, 4)};

s[23] = t[2];

cout << t[0].module() << endl;

return 0;
}

Output
6.40312

23.

Zde je příklad deklarace plné třídy:

using namespace std;
#include <iostream>
#include <cmath>

class vector
{
public:

double x;
double y;

vector (double = 0, double = 0);

vector operator + (vector);
vector operator - (vector);
vector operator - ();
vector operator * (double a);
double module();
void set_length (double = 1);
};

vector::vector (double a, double b)
{
x = a;
y = b;
}

vector vector::operator + (vector a)
{
return vector (x + a.x, y + a.y);
}

vector vector::operator - (vector a)
{
return vector (x - a.x, y - a.y);
}

vector vector::operator - ()
{
return vector (-x, -y);
}

vector vector::operator * (double a)
{
return vector (x * a, y * a);
}

double vector::module()
{
return sqrt (x * x + y * y);
}

void vector::set_length (double a)
{
double length = this->module();

x = x / length * a;
y = y / length * a;
}

ostream& operator << (ostream& o, vector a)
{
o << "(" << a.x << ", " << a.y << ")";
return o;
}

int main ()
{
vector a;
vector b;
vector c (3, 5);

a = c * 3;
a = b + c;
c = b - c + a + (b - a) * 7;
c = -c;

cout << "The module of vector c: " << c.module() << endl;

cout << "The content of vector a: " << a << endl;
cout << "The opposite of vector a: " << -a << endl;

c.set_length(2); // Transformuje c ve vektoru o velikosti 2.

a = vector (56, -3);
b = vector (7, c.y);

b.set_length(); // Transformuje b v jednotné vektoru.

cout << "The content of vector b: " << b << endl;

double k;
k = vector(1, 1).module(); // K budou obsahovat 1.4142.
cout << "k contains: " << k << endl;

return 0;
}

Output
The module of vector c: 40.8167
The content of vector a: (3, 5)
The opposite of vector a: (-3, -5)
The content of vector b: (0.971275, 0.23796)
k contains: 1.41421

Je také možné definovat funkci, která vytváří součet dvou vektorů bez uvedení ji do definice vektoru třídy. Pak to nebude metoda třídy vektoru, ale spíše jen funkce, která používá vektory:

vector operator + (vector a, vector b)
{
return vector (a.x + b.x, a.y + b.y);
}

V příkladu definice plné třídy, výše, je definováno násobení vektoru dvojitým. Předpokládejme, že chceme násobení dvojitý vektorem, které mají být definovány také. Pak musíme napsat izolovanou funkci mimo třídy:

vector operator * (double a, vector b)
{
return vector (a * b.x, a * b.y);
}

Samozřejmě, že klíčová slova new a delete práci pro instancí tříd taky. A co víc, new automaticky volá konstruktor, aby se inicializovat objekty a delete automaticky zavolá destruktor před zrušení přidělení paměti proměnných instance přijímat:

using namespace std;
#include <iostream>
#include <cmath>

class vector
{
public:

double x;
double y;

vector (double = 0, double = 0);

vector operator + (vector);
vector operator - (vector);
vector operator - ();
vector operator * (double);
double module();
void set_length (double = 1);
};

vector::vector (double a, double b)
{
x = a;
y = b;
}

vector vector::operator + (vector a)
{
return vector (x + a.x, y + a.y);
}

vector vector::operator - (vector a)
{
return vector (x - a.x, y - a.y);
}

vector vector::operator - ()
{
return vector (-x, -y);

}

vector vector::operator * (double a)
{
return vector (a * x, a * y);
}

double vector::module()
{
return sqrt (x * x + y * y);
}

void vector::set_length (double a)
{
vector &the_vector = *this;

double length = the_vector.module();

x = x / length * a;
y = y / length * a;
}

ostream& operator << (ostream& o, vector a)
{
o << "(" << a.x << ", " << a.y << ")";
return o;
}

int main ()
{
vector c (3, 5);

vector *r; // r je ukazatel na vektoru.

r = new vector; // nový přiděluje paměť nutná
cout << *r << endl; // držet a vektorů proměnnou,
// volá konstruktor, který bude
// inicializuje na 0, 0. A nakonec
// nové vrátí adresu vektoru.

r->x = 94;
r->y = 345;
cout << *r << endl;

*r = vector (94, 343);
cout << *r << endl;

*r = *r - c;
r->set_length(3);
cout << *r << endl;

*r = (-c * 3 + -*r * 4) * 5;
cout << *r << endl;

delete r; // Volá vektor destruktor poté
// uvolní paměť.

r = &c; // r ukazuje na vector c
cout << *r << endl;

r = new vector (78, 345); // Vytvoří nový vektor.
cout << *r << endl; // Konstruktor bude inicializaci
// vektorů x a y na 78 a 345

cout << "x component of r: " << r->x << endl;
cout << "x component of r: " << (*r).x << endl;

delete r;

r = new vector[4]; // vytvoří matici 4 vektorů

r[3] = vector (4, 5);
cout << r[3].module() << endl;

delete [] r; // vymazat řada

int n = 5;
r = new vector[n]; // Roztomilý!

r[1] = vector (432, 3);
cout << r[1] << endl;

delete [] r;

return 0;
}

Output
(0, 0)
(94, 345)
(94, 343)
(0.77992, 2.89685)
(-60.5984, -132.937)
(3, 5)
(78, 345)
x component of r: 78
x component of r: 78
6.40312
(432, 3)

24.

Jeden nebo více proměnných v třídě lze prohlásit za static. V takovém případě pouze jedna instance těchto proměnných existují, sdílena všemi instancemi třídy. Je třeba inicializovat mimo deklaraci třídy:

using namespace std;
#include <iostream>

class vector
{
public:

double x;
double y;
static int count;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
count++;
}

~vector()
{
count--;
}
};

int vector::count = 0;

int main ()
{
cout << "Number of vectors:" << endl;

vector a;
cout << vector::count << endl;

vector b;
cout << vector::count << endl;

vector *r, *u;

r = new vector;
cout << vector::count << endl;

u = new vector;
cout << a.count << endl;

delete r;
cout << vector::count << endl;

delete u;
cout << b.count << endl;

return 0;
}

Output
1
2
3
4
3
2

25.

Třída proměnná může být také konstantní. To je stejně jako statická, kromě toho, je přiřazena hodnota v deklaraci třídy a že hodnota nemůže být změněn:

using namespace std;
#include <iostream>

class vector
{
public:

double x;
double y;
const static double pi = 3.1415927;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}

double cylinder_volume ()
{
return x * x / 4 * pi * y;
}
};

int main()
{
cout << "The value of pi: " << vector::pi << endl << endl;

vector k (3, 4);

cout << "Result: " << k.cylinder_volume() << endl;

return 0;
}

Output
The value of pi: 3.14159

Result: 28.2743

26.

Třída může být ODVOZENA z jiné třídy. Nová třída DĚDÍ proměnné a metody BÁZOVĚ TŘÍDĚ. Mezi další proměnné a/nebo metody mohou být přidány:

using namespace std;
#include <iostream>
#include <cmath>

class vector
{
public:

double x;
double y;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}

double module()
{
return sqrt (x*x + y*y);
}

double surface()
{
return x * y;
}
};

class trivector: public vector // trivector je odvozen od vektoru
{
public:
double z; // přidáno do x a y z vektoru

trivector (double m=0, double n=0, double p=0): vector (m, n)
{
z = p; // Vektor konstruktor bude
} // volána před trivector
// konstruktor s parametry
// m a n.

trivector (vector a) // Co dělat v případě, že vektor
{ // se odlévá do trivector
x = a.x;
y = a.y;
z = 0;
}

double module () // define module()pro trivector
{
return sqrt (x*x + y*y + z*z);
}

double volume ()
{
return this->surface() * z; // nebo x * y * z
}
};

int main ()
{
vector a (4, 5);
trivector b (1, 2, 3);

cout << "a (4, 5) b (1, 2, 3) *r = b" << endl << endl;

cout << "Surface of a: " << a.surface() << endl;
cout << "Volume of b: " << b.volume() << endl;
cout << "Surface of base of b: " << b.surface() << endl;

cout << "Module of a: " << a.module() << endl;
cout << "Module of b: " << b.module() << endl;
cout << "Module of base of b: " << b.vector::module() << endl;

trivector k;
k = a; // díky trivector (vektor) definice
// kopie z x a y, k.z = 0
vector j;
j = b; // kopie z x a y. b.z listoval ven

vector *r;
r = &b;

cout << "Surface of r: " << r->surface() << endl;
cout << "Module of r: " << r->module() << endl;

return 0;
}

Output
a (4, 5)    b (1, 2, 3)    *r = b

Surface of a: 20
Volume of b: 6
Surface of base of b: 2
Module of a: 6.40312
Module of b: 3.74166
Module of base of b: 2.23607
Surface of r: 2
Module of r: 2.23607

27.

V programu výše r->module() vypočítává vektorový modul, pomocí x a y, protože r byl prohlášen vektorový ukazatel. Skutečnost, že r ve skutečnosti ukazuje na trivector se nebere v úvahu. Pokud chcete, aby program pro kontrolu typ špičatým předmětem a zvolit vhodnou metodu, pak musí prohlásit, že metody jako virtual uvnitř základní třídy.

(Je-li alespoň jedna z metod bázové třídě je virtuální pak "záhlaví" 4 bajty se přidá do každé instanci tříd. To umožňuje, aby program a stanoví, co je vektor ve skutečnosti ukazuje na.) (4 bajty je pravděpodobně implementace specifické. v 64 bitovém stroji možná je 8 bytů...)

using namespace std;
#include <iostream>
#include <cmath>

class vector
{
public:

double x;
double y;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}

virtual double module()
{
return sqrt (x*x + y*y);
}
};

class trivector: public vector
{
public:
double z;

trivector (double m = 0, double n = 0, double p = 0)
{
x = m; // Jen pro hru,
y = n; // tady nemám volat vektoru
z = p; // konstruktor a udělám
} // trivector konstruktor dělat
// celou práci. Stejný výsledek.

double module ()
{
return sqrt (x*x + y*y + z*z);
}
};

void test (vector &k)
{
cout << "Test result: " << k.module() << endl;
}

int main ()
{
vector a (4, 5);
trivector b (1, 2, 3);

cout << "a (4, 5) b (1, 2, 3)" << endl << endl;

vector *r;

r = &a;
cout << "module of vector a: " << r->module() << endl;

r = &b;
cout << "module of trivector b: " << r->module() << endl;

test (a);

test (b);

vector &s = b;

cout << "module of trivector b: " << s.module() << endl;

return 0;
}

Output
a (4, 5)    b (1, 2, 3)

module of vector a: 6.40312
module of trivector b: 3.74166
Test result:          6.40312
Test result:          3.74166
module of trivector b: 3.74166

28.

Možná by vás zajímalo, v případě, že třída může být odvozena z více než jedné základní třídy. Odpověď je ano:

using namespace std;
#include <iostream>
#include <cmath>

class vector
{
public:

double x;
double y;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}

double surface()
{
return fabs (x * y);
}
};

class number
{
public:

double z;

number (double a)
{
z = a;
}

int is_negative ()
{
if (z < 0) return 1;
else return 0;
}
};

class trivector: public vector, public number
{
public:

trivector(double a=0, double b=0, double c=0): vector(a,b), number(c)
{
} // Trivector konstruktoru vyvolá vektoru
// konstruktor, pak počet konstruktor,
// a v tomto případě nedělá nic víc.

double volume()
{
return fabs (x * y * z);
}
};

int main ()
{
trivector a(2, 3, -4);

cout << a.volume() << endl;
cout << a.surface() << endl;
cout << a.is_negative() << endl;

return 0;
}

Output
24
6
1

29.

Třída odvození vám umožní postavit více komplexních tříd postavené ze základních tříd. Tam je další aplikace třídy odvození: umožňuje programátorovi psát obecné funkce.

Předpokládejme, že jste definovat základní třídu s žádnými proměnnými. Nemá smysl používat instance této třídy uvnitř vašeho programu. Ale pak si napsat funkci, jejíž účelem je roztřídit instance dané třídy. Tato funkce bude schopen vyřešit jakýkoli typ objektu, za předpokladu, že patří do skupiny odvozené od této základní třídy! Jedinou podmínkou je, že uvnitř každé odvozené definici třídy, jsou všechny metody, které Funkce třídění potřeby jsou správně definovány:

using namespace std;
#include <iostream>
#include <cmath>

class octopus
{
public:

virtual double module() = 0; // = 0 znamená funkce není
// definována. To dělá instance
// této třídy nelze prohlásit.
};

double biggest_module (octopus &a, octopus &b, octopus &c)
{
double r = a.module();
if (b.module() > r) r = b.module();
if (c.module() > r) r = c.module();
return r;
}

class vector: public octopus
{
public:

double x;
double y;

vector (double a = 0, double b = 0)
{
x = a;
y = b;
}

double module()
{
return sqrt (x * x + y * y);
}
};

class number: public octopus
{
public:

double n;

number (double a = 0)
{
n = a;
}

double module()
{
if (n >= 0) return n;
else return -n;
}
};

int main ()
{
vector k (1,2), m (6,7), n (100, 0);
number p (5), q (-3), r (-150);

cout << biggest_module (k, m, n) << endl;
cout << biggest_module (p, q, r) << endl;

cout << biggest_module (p, q, n) << endl;

return 0;
}

Output
100
150
100

Možná si myslíte, že "v pořádku, to je dobrý nápad pro odvození třídy z třídy octopus, protože to tak, jak jsem ji rovněž použít pro případy metod a funkcí mé třídě, že byly navrženy ve všeobecném smyslu pro třídu octopus. Ale co když je tu další základna třída s názvem cuttlefish, který má velmi zajímavé metody a funkce taky? musím dělat moji volbu mezi octopus a cuttlefish, když chci odvodit třídu?" Ne, samozřejmě že ne. Odvozená třída může být odvozen z obou octopus a cuttlefish. To je POLYMORFISMUS. Odvozená třída má jednoduše definovat metody nezbytné pro octopus společně s metodami potřebnými pro cuttlefish:

class octopus
{
virtual double module() = 0;
};

class cuttlefish
{
virtual int test() = 0;
};

class vector: public octopus, public cuttlefish
{
double x;
double y;

double module ()
{
return sqrt (x * x + y * y);
}

int test ()
{
if (x > y) return 1;
else return 0;
}
}

30.

Public: směrnice znamená proměnné nebo níže uvedené metody lze přistupovat a používat kdekoliv v programu.

Chcete-li proměnné a metody, aby byly přístupné pouze metodami třídy A způsobů odvozených tříd, pak musíte dát klíčové slovo protected: před nimi.

Chcete-li proměnné nebo metody, které jsou přístupné POUZE metodami třídy, pak musíte dát klíčové slovo private: před nimi.

Skutečnost, že proměnné nebo metody jsou deklarovány private nebo chráněné znamená, že nic externí ke třídě lze získat a používat. To je zapouzdření. (Chcete-li dát určitou funkci právo na přístup k tyto proměnné a metody, pak musí obsahovat prototyp tuto funkci je uvnitř definice třídy, jemuž předchází klíčového slovo friend.)

Dobrá praxe je zapouzdřit všechny proměnné třídy. To může znít divně, pokud jste zvyklí na Struktury v C. Skutečně struct smysl jen tehdy, pokud máte přístup k jeho dat... V jazyce C++ je nutné vytvořit metody přístupovými dat uvnitř třídy. Níže uvedený příklad používá základní příklad kapitole 17, přesto prohlašuje dat třídy mají být chráněna:

using namespace std;
#include <iostream>

class vector
{
protected:

double x;
double y;

public:

void set_x (int n)
{
x = n;
}
void set_y (int n)
{
y = n;
}
double surface ()
{
double s;
s = x * y;
if (s < 0) s = -s;
return s;
}
};

int main ()
{
vector a;

a.set_x (3);
a.set_y (4);

cout << "The surface of a: " << a.surface() << endl;

return 0;
}

Output
The surface of a: 12

Výše uvedený příklad je poněkud zvláštní, protože datové třídy X a Y mohou být nastaveny, ale nelze přečíst zpět. Jakýkoli pokus ve funkci main () ke čtení a.x nebo a.y bude mít za následek chyby kompilace. V dalším příkladu, x a y mohou být zopakovány:

using namespace std;
#include <iostream>

class vector
{
protected:

double x;
double y;

public:

void set_x (int n)
{
x = n;
}
void set_y (int n)
{
y = n;
}

double get_x ()
{
return x;
}
double get_y ()
{
return y;
}
double surface ()
{
double s;
s = x * y;
if (s < 0) s = -s;
return s;
}
};

int main ()
{
vector a;

a.set_x (3);
a.set_y (4);

cout << "The surface of a: " << a.surface() << endl;
cout << "The width of a: " << a.get_x() << endl;
cout << "The height of a: " << a.get_y() << endl;

return 0;
}

Output
The surface of a: 12
The width of a:   3
The height of a:  4

V jazyce C++ člověk neměl přístup k datům třídy přímo. Metody mají být deklarován. Proč tomu tak je? Existuje mnoho důvodů. Jedním z nich je, že to umožňuje změnit způsob, jakým jsou data reprezentována v rámci třídy. Dalším důvodem je to umožňuje data uvnitř třídy, aby bylo možné navzájem závislé. Předpokládejme, že x a y musí být vždy ve stejné znaménko, jinak ošklivé, co se může stát... Je-li jedna povolen přístup k datům třídy přímo, bylo by snadno uložit říci pozitivní x a y negativní. V níže uvedeném příkladu, to je přísně kontrolován:

using namespace std;
#include <iostream>

int sign (double n)
{
if (n >= 0) return 1;
return -1;
}

class vector
{
protected:

double x;
double y;

public:

void set_x (int n)
{
x = n;
if (sign (x) != sign(y)) y = -y;
}
void set_y (int n)
{
y = n;
if (sign (y) != sign(x)) x = -x;
}

double get_x ()
{
return x;
}
double get_y ()
{
return y;
}
double surface ()
{
double s;
s = x * y;
if (s < 0) s = -s;
return s;
}
};

int main ()
{
vector a;

a.set_x (-3);
a.set_y (4);

cout << "The surface of a: " << a.surface() << endl;
cout << "The width of a: " << a.get_x() << endl;
cout << "The height of a: " << a.get_y() << endl;

return 0;
}

Output
The surface of a: 12
The width of a:   3
The height of a:  4

31.

Mluvme o vstup/výstup. V jazyce C++, která je velmi široká.

Zde je program, který zapíše do souboru:

using namespace std;
#include <iostream>
#include <fstream>

int main ()
{
fstream f;

f.open("test.txt", ios::out);

f << "This is a text output to a file." << endl;

double a = 345;

f << "A number: " << a << endl;

f.close();

return 0;
}

Content of file test.txt
This is a text output to a file.
A number: 345

Zde je program, který čte ze souboru:



using namespace std;
#include <iostream>
#include <fstream>

int main ()
{
fstream f;
char c;

cout << "What's inside the test.txt file" << endl;
cout << endl;

f.open("test.txt", ios::in);

while (! f.eof() )
{
f.get(c); // Nebo c = f.get()
cout << c;
}

f.close();

return 0;
}

Output
This is a text output to a file.
A number: 345

32.

Obecně lze říci, že je možné dělat na znakových polí stejný postup jako u souborů. To je velmi užitečné pro konverzi dat nebo správu paměti pole.

Zde je program, který píše uvnitř pole znaků:

using namespace std;
#include <iostream>
#include <strstream>
#include <cstring>
#include <cmath>

int main ()
{
char a[1024];
ostrstream b(a, 1024);

b.seekp(0); // Začněte od prvního znaku.
b << "2 + 2 = " << 2 + 2 << ends; // ( ends, ne endl )
// ends je prostě
// znak null '\0'
cout << a << endl;

double v = 2;

strcpy (a, "A sinus: ");

b.seekp(strlen (a));
b << "sin (" << v << ") = " << sin(v) << ends;

cout << a << endl;

return 0;
}

Output
2 + 2 = 4
A sinus: sin (2) = 0.909297

Program, který čte z řetězce znaků:

using namespace std;
#include <iostream>
#include <strstream>
#include <cstring>

int main ()
{
char a[1024];
istrstream b(a, 1024);

strcpy (a, "45.656");

double k, p;

b.seekg(0); // Začněte od prvního znaku.
b >> k;

k = k + 1;

cout << k << endl;

strcpy (a, "444.23 56.89");

b.seekg(0);
b >> k >> p;

cout << k << ", " << p + 1 << endl;

return 0;
}

Output
46.656
444.23, 57.89

33.

Tento program provádí formátovaný výstup dvěma různými způsoby. Upozorňujeme, že width() a setw() MODIFIKÁTORY jsou účinné pouze na další výstup položku do potoka. Následné položky nebudou ovlivněna.

using namespace std;
#include <iostream>
#include <iomanip>

int main ()
{
int i;

cout << "A list of numbers:" << endl;
for (i = 1; i <= 1024; i *= 2)
{
cout.width (7);
cout << i << endl;
}

cout << "A table of numbers:" << endl;
for (i = 0; i <= 4; i++)
{
cout << setw(3) << i << setw(5) << i * i * i << endl;
}

return 0;
}

Output
A list of numbers:
      1
      2
      4
      8
     16
     32
     64
    128
    256
    512
   1024
A table of numbers:
  0    0
  1    1
  2    8
  3   27
  4   64

Nyní máte základní znalosti o C++. Uvnitř dobrých knih se dozvíte mnohem více věcí. Systém pro správu souborů je velmi silný, má i mnoho dalších možností, než jsou zde ukázány. K dispozici je také mnohem více říci o třídách: šablony tříd, virtuální třídy...

Aby bylo možné efektivně pracovat s C++, budete potřebovat dobrý referenční knihy, stejně jako budete potřebovat jeden pro C. Dále budete potřebovat informace o tom, jak C++ se používá v konkrétní oblasti činnosti. Normy, globální přístup, triky, typické problémech a jejich řešení... Nejlepší reference je samozřejmě knihy napsané Bjarne Stroustrup sám (Nevzpomínám si, kdo z nich jsem četl). Následující Kniha obsahuje téměř každý detail o C a C++, je konstruován podobným způsobem tohoto textu a obsahuje CD:

Jamsa's C/C++ Programátor Bible
&copyright; 1998 Jamsa Press

Las Vegas, Spojené Státy Americké

Francouzské vydání:
C/C++ La Bible du programmeur
Kris Jamsa, Ph.D - Lars Klander
Francie: Editions Eyrolles
www.eyrolles.com
Kanada: Les Editions Reynald Goulet inc.
www.goulet.ca
ISBN 2-212-09058-7

To bylo zastaralé a je nyní:
Jamsa's C/C++ /C# Programátor Bible
Onword Press

Ostatní odkazu:

accu:  www.accu.org/bookreviews/public/reviews/0hr/index.htm

CoderSource.net:  www.codersource.net

C++ Průvodce:  google-styleguide.googlecode.com/svn/trunk/cppguide.xml

C ++ Odkazu: fresh2refresh.com/c/c-language-history

 

Podobný výukový program pro Ada je k dispozici na adrese http://www.adahome.com/Ammo/cpp2ada.html

Haskell tutoriál do C programátor: learnyouahaskell.com

 

Ráda bych poděkovala Didier Bizzarri, Toni Ronkko, Frédéric Cloth, Jack Lam, Morten Brix Pedersen, Elmer Fittery, Ana Yuseepi, William L. Dye, Bahjat F. Qaqish, Muthukumar Veluswamy, Marco Cimarosti, Jarrod Miller, Nikolaos Pothitos, Ralph Wu, Dave Abercrombie, Alex Pennington, Scott Marsden, Robert Krten, Dave Panter, Cihat Imamoglu, Bohdan Zograf, David L. Markowitz, Marko Pozner, Filip Zaludek a Kevin Wheeler pro jejich inspiraci, rady, pomoc, dat, zprávy o chybách, referencí, zvýšení Anglického textu a překladu.

Eric Brasseur - 23 února 1998 do 4 června 2014

Original English text: http://www.4p8.com/eric.brasseur/cppcen.html
Hlavní stránka