Statické datové typy c. Statické metody v Javě

Členy třídy lze použít s klíčové slovo statický. V tomto kontextu je jeho význam podobný tomu, který má v C. Když je člen třídy deklarován jako statický, kompilátor je tím instruován, že by měla existovat pouze jedna kopie tohoto člena, bez ohledu na to, kolik objektů této třídy je vytvořeno. . Statický člen je sdílen všemi objekty dané třídy. Všechna statická data jsou při vytvoření prvního objektu inicializována na nulu a žádná další inicializace se neposkytuje.

Když deklarujete statický datový člen třídy, člen není definován. Místo toho pro ně musíte poskytnout globální definici mimo třídu. To se provádí opětovnou deklarací statické proměnné pomocí operátoru oboru k identifikaci třídy, do které proměnná patří. To je nezbytné, aby byla pro statickou proměnnou alokována paměť.

Jako příklad zvažte další program:

#zahrnout
počítadlo tříd (
statický počet int;
veřejnost:
void setcount(int i) (count = i;);
void showcount()(cout<< count << " "; }
};
int counter::count; // definice počtu
int main() (
čítač a, b;
a.showcount(); // výstupy 0
b.showcount(); // výstupy 0
a.setcount(10); // nastavení statického počtu na 10
a.showcount(); // vytiskne 10
b.showcount(); // také výstupy 10
návrat 0;
}

V první řadě si dejte pozor na to, že statická proměnná typu integer count je deklarována na dvou místech: ve třídě counter a dále jako globální proměnná. Borland C++ inicializuje počet na nulu. To je důvod, proč první volání funkce showcount() vrátí nulu. Potom objekt a nastaví počet na 10. Potom oba objekty a a b zobrazí pomocí funkce showcount() stejnou hodnotu, 10. Protože existuje pouze jedna kopie počtu sdílená objekty a a b, výstup je v obou případech hodnota je 10.

Je také možné mít statické členské funkce. Statické členské funkce nemohou přímo odkazovat na nestatická data nebo nestatické funkce deklarované ve své třídě. Důvodem je, že pro ně neexistuje tento ukazatel, takže neexistuje způsob, jak zjistit, se kterými nestatickými daty pracovat. Pokud například existují dva objekty třídy, které obsahují statickou funkci f(), a pokud se f() pokouší o přístup k nestatické proměnné var definované touto třídou, jak lze určit, která kopie var by měla být použita ? Kompilátor nemůže takový problém vyřešit. To je důvod, proč statické funkce mohou přistupovat pouze k jiným statickým funkcím nebo statickým datům. Statické funkce také nemohou být virtuální nebo deklarované s modifikátory const nebo volatile. Statická funkce může být volána buď pomocí objektu třídy, nebo pomocí názvu třídy a operátoru oboru. Nesmíme však zapomínat, že ani při volání statické funkce pomocí objektu není předán tento ukazatel.

Následující krátký program ilustruje jeden z mnoha způsobů použití statických funkcí. Poměrně běžnou situací je situace, kdy potřebujete poskytnout přístup k omezenému prostředku, jako je například sdílený soubor v síti. Jak tento program ilustruje, použití statických dat a funkcí poskytuje metodu, pomocí které může objekt kontrolovat stav zdroje a pokud je to možné, přistupovat k němu.

#zahrnout


přístup do třídy (
statický výčet access_t acs;
// ...
veřejnost:


{
vrátit acs;
}
// ...
};

int main()
{
přístup obj1, obj2;
access::set_access(uzamčeno); // volání pomocí názvu třídy
// ... kód

if (obj2.get_access()==odemčeno) ( // volání pomocí objektu

cout<< "Access resource.\n";
}
jinak cout<< "Locked out.\n";
// ...
návrat 0;
}

Po spuštění tohoto programu se na obrazovce objeví „uzamčeno“. Všimněte si, že funkce set_access() se volá s názvem třídy a operátorem oboru. Funkce get_access() se volá s objektem a operátorem tečka. Při volání statické funkce lze použít kteroukoli z těchto forem a obě mají stejný účinek. Vyplatí se s tímto programem trochu experimentovat, abyste se ujistili, že rozumíte tomu, jak funguje.

Jak bylo uvedeno, statické funkce mají přímý přístup pouze k jiným statickým funkcím nebo statickým datům v rámci stejné třídy. Chcete-li to zkontrolovat, pokusme se zkompilovat následující verzi programu:

// tento program obsahuje chybu a nebude kompilován
#zahrnout
enum access_t (shared, in_use, locked, unlocked);
// třída ovládá vzácný zdroj
přístup do třídy (
statický výčet access_t acs;
int i; // není statické
// ...
veřejnost:
static void set_access (enum access_t a) (acs = a;)
statický výčet access_t get_access()
{
i = 100; // se nezkompiluje
vrátit acs;
}
// ...
};
enum access_t access::acs; // definice acs
int main()
{
přístup obj1, obj2;
access::set_access(uzamčeno); // volání pomocí názvu třídy
// ... kód
// může obj2 přistupovat ke zdroji
if(obj2.get_access()==odemčeno) ( // volání pomocí objektu
access::set_access(in_use); // volání pomocí názvu třídy
cout<< "Access resource.\n";
}
jinak cout<< "Locked out.\n";
// ...
}

Tento program se nezkompiluje, protože funkce get_access() se pokouší o přístup k nestatické proměnné.

Zpočátku možná nepocítíte okamžitou potřebu používat statické členy, ale jak získáte více zkušeností s programováním v C++, stanou se v určitých situacích velmi užitečné, protože se vyhýbají použití globálních proměnných.

Většina klíčových slov C++ dělá jednu věc. Int se používá k deklaraci celočíselné proměnné, buď když funkce vrátí celočíselnou hodnotu, nebo vezme celé číslo jako argument. Operátor new použijete k přidělení paměti a operátor delete k jejímu uvolnění. Můžete použít const k označení, že hodnotu proměnné nelze změnit. Ironií je, že statické klíčové slovo, i když znamená „nezměnitelné“, má mnohonásobné (a zjevně nesouvisející) použití. Klíčové slovo statické lze použít ve třech hlavních kontextech:

  • uvnitř funkce;
  • uvnitř definice třídy;
  • před globální proměnnou v souboru, který tvoří vícesouborový program.

Nejjednodušší je použít statiku uvnitř funkce. To jednoduše znamená, že jakmile byla proměnná inicializována, zůstane v paměti až do konce programu. Můžete si to představit jako proměnnou, která si uchovává svou hodnotu, dokud se program nedokončí. Můžete například použít statickou proměnnou k zaznamenání počtu volání funkce jednoduchým přidáním řádků static int count = 0; a počítat++; do funkce. Protože počet je statická proměnná, řádek static int count = 0; bude proveden pouze jednou. Kdykoli je funkce volána, bude mít count poslední hodnotu, která jí byla přidělena.

Můžete také použít statiku způsobem, který zabrání opětovné inicializaci proměnné uvnitř smyčky. Například v následujícím kódu bude proměnná number_of_times rovna 100, i když řádek static int number_of_times = 0; je umístěn uvnitř smyčky, kde se zdá, že je spuštěn pokaždé, když program dosáhne smyčky. Trik je v tom, že klíčové slovo static zabraňuje opětovné inicializaci proměnné. Jednou z věcí při použití klíčového slova static je, že automaticky nastaví proměnnou na hodnotu null – ale nespoléhejte se na to (to vaše záměry nejsou jasné).

For(int ix=0; ix< 10; ix++) { for(int iy = 0; iy < 10; iy++) { static int number_of_times = 0; number_of_times++; } }

Statické proměnné můžete použít k uložení informací o poslední hodnotě vrácené funkcí, například pokud chcete uložit maximální hodnotu vypočítanou funkcí. Pokud analyzujete řetězec, můžete také uložit poslední znak vrácený funkcí, abyste jej mohli zavolat s argumentem označujícím, že by měla vrátit poslední znak.

Druhé použití static je uvnitř definice třídy. Ačkoli většina proměnných deklarovaných v rámci třídy může mít v každé instanci třídy jinou hodnotu, statická pole třídy budou mít stejný význam pro všechny instance dané třídy a ani není nutné vytvářet instanci této třídy. Je užitečné myslet na statické proměnné třídy jako na uchovávající informace potřebné k vytvoření nových objektů (například v továrně tříd). Pokud například chcete očíslovat instance třídy, můžete použít statickou proměnnou ke sledování posledního použitého čísla. Je důležité poznamenat, že dobrou praxí při používání statických proměnných třídy je používat název_třídy::x; , nikoli instance_třídy.x; . To pomáhá programátorovi připomenout, že statické proměnné nepatří do jediné instance třídy a že nemusíte vytvářet instanci této třídy. Jak jste si možná všimli, můžete použít operátor rozsahu, ::, pro přístup k statice, když k ní přistupujete prostřednictvím názvu třídy.

Při ladění nebo implementaci programu pomocí statiky je důležité mít na paměti, že jej nemůžete inicializovat uvnitř třídy. Ve skutečnosti, pokud se rozhodnete zapsat celý kód třídy do hlavičkového souboru, nebudete moci ani inicializovat statickou proměnnou uvnitř hlavičkového souboru; proveďte to v souboru .cpp. Kromě toho musíte inicializovat statické členy třídy, jinak nebudou v rozsahu. (Syntaxe je trochu zvláštní: zadejte název_třídy::statická_proměnná = hodnota .)

Můžete mít také funkce statické třídy. Statické funkce jsou funkce, které nevyžadují instanci třídy a jsou volány stejným způsobem, analogicky se statickými proměnnými, se jménem třídy, a ne se jménem objektu. Například a_class::static_function(); , ne an_instance.function(); . Statické funkce mohou pracovat pouze se statickými členy třídy, protože neodkazují na konkrétní instance třídy. Statické funkce lze použít ke změně statických proměnných, ke sledování jejich hodnot - například můžete použít statickou funkci, pokud se rozhodnete použít čítač, abyste každé instanci třídy dali jedinečný identifikátor.

Můžete například použít následující kód:

Class user ( private: int id; static int next_id; public: static int next_user_id() ( next_id++; return next_id; ) // další metody pro uživatelskou třídu user() // konstruktor třídy ( id = user::next_id++; / / nebo volání metody, id = user.next_user_id(); ) ); int user::next_id = 0;

Pamatujte, že při nastavování musíte uvést typ statické proměnné!

Uživatel a_user;

nastaví ID na další ID číslo, které nepoužívá žádný jiný uživatelský objekt. Všimněte si, že je dobrým stylem deklarovat identifikátor jako konstantu.

Poslední použití static je jako globální proměnná v souboru kódu. V tomto případě použití static znamená, že zdrojový kód v jiných souborech, které jsou součástí projektu, nemá přístup k proměnné. Proměnnou může vidět pouze kód uvnitř stejného souboru (její rozsah je omezen na soubor). Tuto techniku ​​lze použít k modelování objektově orientovaného kódu, protože omezuje viditelnost proměnných a pomáhá tak vyhnout se konfliktům pojmenování. Tento způsob použití statiky je pozůstatkem C.

Kromě modifikátoru přístupu můžete před název pole, metody nebo vlastnosti napsat klíčové slovo statický .
« statický “ znamená, že toto pole, metoda nebo vlastnost nebude patřit každému objektu třídy, ale všem dohromady.

Klasický příklad: jak zjistit, kolik objektů stejné třídy bylo vytvořeno? K vyřešení tohoto problému slouží přesně statická pole a metody.

Podívejme se na příklad tygrů. Pojďme definovat třídu" Tygr" Pokud zapíšeme pole třídy takto: veřejný počet int; pak každý objekt bude mít toto pole a každý objekt bude mít své vlastní. Navíc, pokud nebude vytvořen jediný objekt, pak toto pole nebude vůbec existovat.
Proto udělejme toto pole statické ( statický).

Vytvořme konstruktor, ve kterém budeme zvyšovat počítadlo počet při vytváření každého nového objektu:
public Tiger() ( count++; ).
Zde můžeme nastavit jednotlivé vlastnosti tygra: váha, výška, přezdívka.

Pojďme také napsat statickou metodu, která zobrazí počet vytvořených objektů:
public static void ShowNumberOfObjects().

Potom bude naše konzolová aplikace mít dvě třídy:

Public class Tiger ( public static int count; public static Tiger() ( count++; ) public static void ShowNumberOfObjects() ( Console.WriteLine("Tigers = (0)", Tiger.count.ToString()); ) ) class Program ( static void Main(string args) ( // Jaký je počet tygrů bez vytvoření objektů? Tiger.ShowNumberOfObjects(); // 0, protože jsme ještě nevytvořili objekty // Vytvořme 3 tygry Tiger t1 = new Tiger () ; Tiger t2 = nový tygr (); Tiger t3 = nový tygr (); Tiger.ShowNumberOfObjects(); // 3 tygři budou uvolněni Console.ReadLine(); ) )

Výsledek: 3.

Závěr. Statická metoda vám umožňuje volat ji bez jakýchkoli objektů. Místo názvu objektu se při volání metody zadává název třídy Tiger: Tiger.ShowNumberOfObjects();

Rozdíly mezi statickou a nestatickou metodou:

1. K volání statické metody není potřeba objekt.
2. Uvnitř statické metody není k dispozici proměnná this, která ukazuje na objekt, a proto nejsou dostupná všechna nestatická pole této třídy, protože jako by tam nebyl žádný předmět.
3. Uvnitř běžné metody jsou k dispozici statická i nestatická pole.
4. Počínaje C# 4.0 bylo možné učinit samotnou třídu statickou.

Někdy jsou vytvořeny třídy, které se skládají pouze ze statických metod, jako je třída Math. Takové třídy jsou v podstatě kontejnery globálních funkcí, ale to se odchyluje od konceptu OOP. Bude také nemožné vytvořit instance statické třídy.

Nyní pochopíme pojem „struktura“ a zjistíme její rozdíl od třídy.

Poslední aktualizace: 10.08.2017

Kromě proměnných a metod, které se vztahují přímo k objektu, vám C++ umožňuje definovat proměnné a metody, které se přímo týkají třídy nebo jinak statických členů třídy. Statické proměnné a metody platí pro celou třídu. K jejich definování se používá klíčové slovo static.

Například banka může mít mnoho různých vkladů, ale všechny vklady budou mít nějaké společné úrokové sazby. K popisu bankovního účtu tedy definujeme a používáme následující třídu:

#zahrnout class Účet ( public: Account(double sum) ( this->sum = sum; ) static int getRate() ( return rate; ) static void setRate(int r) (rate = r; ) double getIncome() ( return sum + součet * sazba / 100; ) private: double sum; static int rate; ); int Účet::rate = 8; int main() ( Účet účet1(20000); Účet účet2(50000); Účet::setRate(5); // resetování hodnoty sazby std::cout<< "Rate: " << Account::getRate() << std::endl; std::cout << "Rate: " << account1.getRate() << " Income: " << account1.getIncome() << std::endl; std::cout << "Rate: " << account2.getRate() << " Income: " << account2.getIncome() << std::endl; return 0; }

Třída Account definuje jednu sazbu statické proměnné a dvě statické funkce pro řízení této proměnné. Při definici statických funkcí stojí za zvážení, že uvnitř nich můžeme používat pouze statické proměnné třídy, jako je například proměnná rate. Nestatické proměnné nelze použít ve statických funkcích.

Navíc tento ukazatel nelze použít ve statických funkcích, což je v zásadě zřejmé, protože ukazuje na aktuální objekt a statické funkce odkazují na celou třídu.

Je také důležité, že pokud třída obsahuje statické proměnné, musí být navíc definovány mimo třídu:

Int Account::rate = 8;

Přiřazení počáteční hodnoty proměnné je volitelné.

Za zmínku také stojí, že protože statické členy odkazují na celou třídu, název třídy následovaný operátorem :: se používá k odkazování na statické členy. Nebo můžeme také přistupovat k veřejným členům třídy prostřednictvím proměnných této třídy:

Account::getRate() account1.getRate()

Konzolový výstup programu:

Sazba: 5 Sazba: 5 Příjem: 21000 Sazba: 5 Příjem: 52500

Ve třídách je také běžné používat statické konstanty. Udělejme například proměnnou sazby ve třídě Účet jako konstantu:

#zahrnout class Účet ( public: const static int rate = 8; Account(double sum) ( this->sum = sum; ) double getIncome() ( return sum + sum * rate / 100; ) private: double sum; ); int main() ( účet účet1(20000); účet účet2(50000); std::cout<< "Rate: " << account1.rate << "\tIncome: " << account1.getIncome() << std::endl; std::cout << "Rate: " << account2.rate << "\tIncome: " << account2.getIncome() << std::endl; return 0; }

Na rozdíl od statických proměnných není třeba statické konstanty dále definovat mimo třídu.

Lekce 25. Statické funkce a datové členy

Až dosud měl každý objekt, který jste vytvořili, svou vlastní sadu datových prvků. V závislosti na účelu vaší aplikace mohou nastat situace, kdy objekty stejné třídy musí sdílet jeden nebo více datových prvků. Předpokládejme například, že píšete mzdový program, který sleduje pracovní dobu 1 000 zaměstnanců. Pro stanovení daňové sazby musí program znát podmínky, ve kterých každý zaměstnanec pracuje. K tomu použijeme proměnnou třídy stav_práce. Pokud však všichni zaměstnanci pracují za stejných podmínek, váš program může sdílet tento datový prvek mezi všemi objekty typu zaměstnanec. Váš program tedy snižuje množství potřebné paměti tím, že zahodí 999 kopií stejných informací. Chcete-li sdílet prvek třídy, musíte tento prvek deklarovat jako statický (statický). Tento kurz popisuje kroky, které musíte provést, abyste mohli sdílet prvek třídy mezi více objekty. Na konci této lekce si osvojíte následující základní pojmy:

    C++ vám umožňuje mít objekty stejného typu, které sdílejí jednoho nebo více členů třídy.

    Pokud váš program přiřadí hodnotu sdílenému prvku, pak všechny objekty této třídy mají okamžitě přístup k této nové hodnotě.

    Chcete-li vytvořit sdílený datový člen třídy, musíte před jméno člena třídy zadat klíčové slovo statický.

    Poté, co program deklaruje prvek třídy jako statický musí deklarovat globální proměnnou (mimo definici třídy), která odpovídá danému sdílenému členu třídy.

    Vaše programy mohou používat klíčové slovo statický aby bylo možné metodu třídy volat, zatímco program možná ještě nedeklaroval žádné objekty této třídy.

SDÍLENÍ DATOVÉHO PRVKU

Obvykle, když vytvoříte objekty určité třídy, každý objekt získá svou vlastní sadu datových členů. Mohou však nastat situace, kdy objekty stejné třídy potřebují sdílet jeden nebo více datových prvků (statický např datové prvky). V takových případech deklarujte datové prvky jako obecný bahno A soukromý, a poté zadejte před typ klíčové slovo statický jak je uvedeno níže:

private: static int sdílená_hodnota;

Po deklaraci třídy musíte prvek deklarovat jako globální proměnnou mimo třídu, jak je uvedeno níže:

int název_třídy::sdílená_hodnota;

Třídu definuje následující program SHARE_IT.CPP knižní série, prvek sdílení počet_stránek, který je stejný pro všechny objekty (knihy) třídy (série). Pokud program změní hodnotu tohoto prvku, změna se okamžitě projeví ve všech objektech třídy:

#zahrnout

#zahrnout

třídní kniha_seriál

( public: book_series(char *, char *, float); void show_book(void); void set_pages(int) ; private: static int page_count; char title; char autor[ 64 ]; float price; );

int série_knih::počet_stran;

void book_series::set_pages(int pages)

( page_count = stránky; )

book_series::book_series(znak *název, znak *autor, pohyblivá cena)

( strcpy(série_knihy::název, název); strcpy(série_knihy::autor, autor); řada_knih::cena = cena; )

void book_series:: show_book (void)

(cout<< "Заголовок: " << title << endl; cout << "Автор: " << author << endl; cout << "Цена: " << price << endl; cout << "Страницы: " << page_count << endl; }

( book_series programming("Učíme se programovat v C++", "Jamsa", 22.95); book_series word("Učíme se pracovat s Wordem pro Windows", "Wyatt", 19.95); word.set_pages(256); programming.show_book ( ); word.show_book() ; cout<< endl << "Изменение page_count " << endl; programming.set_pages(512); programming.show_book(); word.show_book(); }

Jak vidíte, třída prohlašuje počet_stránek Jak statický int. Bezprostředně po definici třídy program deklaruje prvek počet_stránek jako globální proměnná. Když program změní prvek počet_stránek, změna se okamžitě projeví ve všech objektech třídy knižní série.

Sdílení členů třídy

V závislosti na vašem programu mohou nastat situace, kdy potřebujete sdílet určitá data mezi více instancemi objektu. Chcete-li to provést, deklarujte prvek jako statický. Dále deklarujte tento prvek mimo třídu jako globální proměnnou. Jakékoli změny, které váš program provede v tomto prvku, se okamžitě projeví v objektech této třídy.

Použití prvků s atributyveřejné statické pokud objekty neexistují

Jak jste se právě dozvěděli, při deklarování prvku třídy jako statický tento prvek je sdílen všemi objekty dané třídy. Mohou však nastat situace, kdy program ještě nevytvořil objekt, ale potřebuje prvek použít. Chcete-li použít prvek, váš program jej musí deklarovat jako veřejnost A statický. Prvek používá například následující program USE_MBR.CPP počet_stránek ze třídy knižní série, i když objekty této třídy neexistují:

#zahrnout

#zahrnout

třídní kniha_seriál

( public: static int page_count; private: char title; char author; float price; );

int série_knih::počet_stran;

void main(void) ( série_knih::počet_stránek = 256; cout<< "Текущее значение page_count равно " << book_series::page_count << endl; }

V tomto případě, protože třída definuje prvek třídy počet_stránek Jak veřejnost program může přistupovat k tomuto prvku třídy, i když objekty třídy knižní série neexistuje.

POUŽÍVÁNÍ FUNKCÍ STATICKÝCH PRVKŮ

Předchozí program ilustroval použití statický datové prvky. Podobně vám C++ umožňuje definovat statický funkce prvků (metody). Pokud tvoříte statický váš program může volat takovou metodu, i když objekty nebyly vytvořeny. Pokud například třída obsahuje metodu, kterou lze použít na datech mimo třídu, můžete tuto metodu vytvořit statický. Níže je třída Jídelní lístek který používá sekvenci esc ovladače ANSI k vymazání obrazovky displeje. Pokud máte v systému nainstalovaný ovladač ANSI.SYS, můžete metodu použít clear_screen k čištění obrazovky. Protože je tato metoda deklarována jako statický, program jej může použít, i když jsou objekty typu Jídelní lístek neexistuje. Následující program CLR_SCR.CPP používá metodu clear_screen Vymazání obrazovky:

#zahrnout

( public: static void clear_screen(void); // Zde by měly být další metody private: int number_of_menu_options; );

void menu::clear_screen(void)

(cout<< "\033" << "}