Organizacja kodu¶
Funkcje i moduły¶
Program – sekwencja instrukcji posiadająca pewną strukturę. Funkcje oraz zmienne mogą być grupowane na dwa sposoby:
Fizyczny – moduły (jednostki translacji) reprezentowane przez pliki, które mogą być kompilowane niezależnie od siebie
Logiczny
Struktury, klasy (paradygmat obiektowy)
Przestrzenie nazw
Pliki nagłówkowe i źródłowe¶
Pliki nagłówkowe (*.h
, *hpp
) zawierają:
Deklaracje stałych
Deklaracje zmiennych globalnych
Deklaracje funkcji
Deklaracje typów
Pliki źródłowe (*.cpp
) zawierają właściwy kod programu, w tym:
Implementację funkcji
Implementację typów
mathematics.h
int square(int x);
int minus(int x, int y);
int plus(int x, int y);
mathematics.cpp
int square(int x)
{
return x * x;
}
int minus(int x, int y)
{
return x – y;
}
int plus(int x, int y)
{
return x + y;
}
Preprocesor¶
Dzięki zastosowaniu preprocesora kod programu może zostać zmodyfikowany zanim zostanie skompilowany dzięki:
dołączaniu zawartości plików nagłówkowych -
#include
kompilacji warunkowej -
#if defined #else #endif
kompilacji warunkowej plików nagłówkowych -
#ifndef XX #define XX #endif
definicjom -
#define XX YY #if XX < YY #elseif
Bariery #include¶
Produkcyjne aplikacje języka C++ korzystają zazwyczaj z wielu plików nagłówkowych, w których niejednokrotnie dochodzi do włączania całych grup kolejnych grup plików nagłówkowych. Należy unikać wielokrotnego pośredniego włączania tego samego pliku nagłówkowego do kompilacji. W tym celu należy korzystać z odpowiednich dyrektyw preprocesora.
#ifndef HDR1_HPP
#define HDR1_HPP
// właściwa zawartość pliku nagłówkowego
#endif
Słowo kluczowe extern¶
Słowo kluczowe extern
umożliwia zdefiniowanie zmiennej, która może być wykorzystywana w różnych modułach programu, ale ma występować w jednym egzemplarzu. Ma być zmienną globalną dla całego programu.
// global.h
#ifndef GLOBAL_H
#define GLOBAL_H
#include <string>
extern int x;
extern std::string s;
#endif
// global.cpp
#include <string>
int x = 7;
std::string s = "Kangur";
// main.cpp
#include <iostream>
#include "global.h"
using namespace std;
int main()
{
cout << "x=" << x << " s=" << s << endl;
}
Przestrzenie nazw¶
Przestrzenie nazw służą logicznemu grupowaniu typów i funkcji.
W przestrzeniach nazw możemy umieszczać dowolne symbole. Użycie symbolu poza przestrzenią nazw, do której należy dany symbol, wymaga poprzedzenia go odpowiednim przedrostkiem. Unikany jest wówczas konflikt nazw oraz jawnie określana jest przynależność symbolu do określonej przestrzeni.
namespace A
{
typedef ... String; // definicja typu A::String
void foo(String); // definicja funkcji A::foo(A::String)
}
namespace B
{
typedef ... String; // definicja typu B::String
void foo(String); // definicja funkcji B::foo(B::String)
}
A::String s1; // tworzy zmienną typu String zadeklarowanego w przestrzeni A
B::String s2; // tworzy zmienną typu String zadeklarowanego w przestrzeni B
A::foo(s1); // wywołuje funkcję foo() zadeklarowaną w przestrzeni A
B::foo(s2); // wywołuje funkcję foo() zadeklarowaną w przestrzeni B
foo(s1); // A::foo(s1)
foo(s2); // B::foo(s2)
Słowo kluczowe using¶
Słowo kluczowe using
umożliwia uniknięcie wielokrotnego stosowania operatora zakresu ::using
może zostać użyte na dwa sposoby, jako:
deklaracja
using
– symbol określonej przestrzeni nazw staje się dostępny lokalnie
using A::String;
dyrektywa
using
– umożliwia zastosowanie wszystkich symboli danej przestrzeni nazw bez użycia operatora zakresu
using namespace A;
using namespace std;
Aliasy przestrzeni nazw¶
Aliasy umożliwiają użycie skrótów dla długich przestrzeni nazw.
namespace American_Telephone_and_Telegraph
{
// ...
}
namespace ATT = American_Telephone_and_Telegraph;
ATT::String s1 = "Grieg";
ATT::String s2 = "Nielsen";