Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /home/www/novacisko.cz/subdomains/bredy/init.php on line 11

Warning: mysql_connect(): Headers and client library minor version mismatch. Headers:50562 Library:100020 in /home/www/novacisko.cz/subdomains/bredy/init.php on line 11

Warning: Cannot modify header information - headers already sent by (output started at /home/www/novacisko.cz/subdomains/bredy/init.php:11) in /home/www/novacisko.cz/subdomains/bredy/index.php on line 38
C++ - Akce a Zpráva jako objekt - Bredyho blog - Ondřej Novák
Bredyho blog - Ondřej Novák

C++ - Akce a Zpráva jako objekt

Akcí nazývám obyčejné volání funkce, zprávou pak volání metody objektu (jak je chápáno podle OOP). Lze vůbec volání čehokoliv reprezentovat jako objekt? A k čemu je to vlastně dobré?


Proč?

Volání čehokoliv není v C++ chápáno jako objekt. Je to zřejmé, zavolat metodu nebo funkci je prostě tak jednoduché, že se nevyplatí nad tímto systémem vytvářet nějaká pravidla objektů (zejména by to zesložitilo vlastní jazyk). Přesto v C++ nalezneme instanci funkce nebo instanci metody a samozřejmě i způsob, jak tyto instance uložit.

Při vytváření typu instance funkce akorát narážíme na dost krkolomné zápisy.
Typ funkce:

typ_navratove_hodnoty (*Jmeno)(... parametry ...)

Typ metody

typ_navratove_hodnoty (Trida::*Jmeno)(... parametry ...)

Instanci objektu volání vytvoříme jednoduše:
Instance volání funkce

&JmenoFunkce

Instance volání metody

&JmenoTridy::JmenoMetody

Zajímavější je pak vyvolání funkce nebo metody na základě této instance.
Volání funkce (pokud proměnná fn obsahuje instanci)

fn( ... parametry ... )

Volání metody (pokud proměnná fn obsahuje instanci a obj je instance objektu)

(obj.*fn)( ... parametry ... )
//nebo
(obj->*fn)( ... parametry ... )

Ačkoliv se v zásadě jedná o pouhé ukazatele na funkce (pozor, u volání virtuální metody zde vystupuje do hry ještě index do vtable), lze instance těchto ukazatelů chápat jako objekty.

Problém je, že samotný objekt volání není moc využitelný, pokud potřebujeme volání nějak dále zpracovávat. Zejména z toho důvodu, že samotné volání neobsahuje parametry, které tam musí dodat volající. Každý objekt představující volání je tak unikátního typu, že jakékoliv další zpracování je možné maximálně tak pomocí šablon.

Třídy Action a Message

Třída Action představuje třídu pro objekty obsahující nejen vlastní volání, ale i parametry. Výhodou je, že sjednocuje vlastní volání tak, že se zavolání minimalizuje na pouze zavolání funkce Run(). Můžeme tedy například připravit volání nějaké funkce jako objekt a ten objekt zaslat nějakému správci úkolů. Správce pak volání v naplánovanou dobu spustí. Jiné využití se naskýtá v vícevláknovém prostředí, pokud nějakou funkci potřebujeme vykonat v jiném vlákně. Pak stačí objekt volání umístit do nějaké schránky (kterou si volané vlákno pravidelně kontroluje) a v jiném vlákně zařídit, aby se takový objekt vykonal.

Třída Message je podobná třídě Action s tím rozdílem, že je omezená pouze na volání metod objektů (Třída Action dovoluje volat jak funkce tak metody). Třída mnohem víc připomíná zprávu z OOP. Definuje kterou metodu zavolat, jaké jí předat parametry, ale nic neříká o tom, kterému objektu se má zaslat (neobsahuje příjemce). Teprve v okamžiku zavolání musí být příjemce dodán. Je samozřejmě možné zprávu zaslat více objektům, což už samo ukazuje na další možnosti.

Šablony Action a Message

Samotné třídy jsou šablony. U třídy Action je totiž nutné specifikovat typ návratové hodnoty. U třídy Message pak ještě navíc třídu objektu, jehož metodu budeme volat.

 Action<bool>
Action<int>
Action<MujObject>
Message<Interface,bool>
Message<Interface,int>
Message<Interface,JinyObjekt>

Je trochu nepříjemné, že ani tady není rozhraní jednotné v případě, že máme funkce s různou návratovou hodnotu. To je problém, třídy samy totiž netuší, zda je návratová hodnota pro volající důležitá a tak předpokládají že je. Pro sjednocení rozhraní lze udělat následující

  1. Použít stejný typ návratové hodnoty pro všechny potencionálně volané funkce/metody
  2. Použít takový typ, do kterého lze návratovou hodnotu převést
  3. Napsat si vlastní variantu objektu Action/Message, která návratovou hodnotu zahodí, nebo jinak zpracuje v rámci volání.
actions.h Zdrojový kód knihovny actions.h

Vytvoření Action nebo Message

Vytvoření akce nebo zprávy není složité. Použijeme funkce z rozhraní:

//vytvoreni akce na funkci
Action<typ>::Make{&funkce, (tuple|... parametry ...));

//vytvoreni akce na metodu
Action<typ>::Make{objref, &metoda (tuple|... parametry ...));

//vytvoreni zprávy
Message<InterfaceRef,typ>::Make(&metoda, (tuple|... parametry ...));

Všimněte si, že se používa tuple pro zadání parametrů. Viz Tuples v C++. jako objref musí být uveden ukazatel na objekt, nebo objekt představující chytrý ukazatel, který definuje operátor operátor ->. Stejně tak typ InterfaceRef představuje ukazatel na typ, jehož metody se volají, nebo třídu chytrého ukazatele, které definuje operátor ->.

Vytvořenou zprávu můžeme ihned použít jako parametr jiné funkce, nebo ji můžeme dynamicky alokovat. A aby jsme nemuseli zjišťovat typ výsledného objektu zprávy pro operátor new, nabízí knihovna funkci Clone

Action<typ> *akce = Clone(Action<typ>::Make{objref, &funkce, (tuple|... parametry ...)));

Vyvolání akce nebo zprávy

Máme-li instanci třídy Action nebo ukazatel na objekt, který dědí tuto třídu, pak stačí zavolat metodu Run

void foo(Action<bool> *akce) { 
bool ret = akce->Run(); //vyvolej připravenou akci
if (ret) {...} //zpracuj výsledek
}

Pokud voláme zprávu, postup je obdobný

void foo(Message<IModel, bool> *zprava) { 
IModel *recp = GetRecipient();
bool ret = zprava->Run(recp); //vyvolej připravenou akci
if (ret) {...} //zpracuj výsledek
}

Požadavky na volanou funkci

Nejsou velké. Akce a Zprávy lze vytvářet pro funkce až do 8 parametrů. Přitom při zpracování akce dojde k rozbalení tuple do parametrů funkce. Při vyšším počtu parametrů dostává funkce nerozbalené tuple.

Využití akcí

Využití akcí a zpráv je široke. Nabízím několik příkladu:

  • Notifikace kolekce objektů
  • Záznam volání (historie) a rekonstrukce historie
  • Undo funkce
  • Odložený start
  • Spuštění akce v jiném vlákně
  • Spouštění akcí na základě příchozích událostí nebo činnosti uživatele.
actions.h Zdrojový kód knihovny actions.h

Dodatek ke knihovně

Součástí knihovny jsou třídy FunctionPointer a MethodPointer v této deklaraci:

   template<class Function, class RetType>
class FunctionPointer
template<class Object, class Function, class RetType>
class MethodPointer

Obě šablony umožňují zabalit volání funkce nebo metody do objektu tak, aby bylo možné funkci zavolat a předat jí parametry pomocí tuple. Navíc obě třídy sjednocují syntaxtický zápis volání:

 funkce((tuple|... parametry ...))
metoda((tuple|... parametry ...))

v případě že funkce je instance třídy FunctionPointer a metoda je instance třídy MethodPointer. Tuple se i v tomto případě rozbaluje do 8 parametrů, pro víc jak 8 parametrů se předává tuple nerozbalené.

vytvořeno: 15.8.2007 10:55:14, změněno: 15.8.2007 19:09:42
Jsou informace v článku pro Vás užitečné?
  • (1)
  • (2)
  • (0)
  • (1)
  • (0)
Nick nebo OpenID
Vzkaz
 
25.7.2016 20:13:30

Em77pQWQ7D

your welcome joiz aside sa sinabi kung reuetrqmenis ng sponsor mo 48r form lang need mo then notarize photo copy ng passport mo its up to you kung gusto mo iinclude photo copy ng marriage certificate nyo and some photos nyo together pero sakin hindi ko na naman sinama yung mga yun!! Good Luck and God Bless

Podobné články

Akce a Zpráva jako objekt v.2

V článku C++ - Akce a Zpráva jako objekt jsem představil dva objekty, jenž slouží k objektovému zabalení volání funkce nebo metody. V tomto článku si představíme vylepšenou druhou verzi.

Distributor - vaše objekty budou o svém okolí vědět vše

Největším problémem většiny UI /ale i ne-IU/ aplikací, které potkávám, je špatná nebo vůbec nevyřešená komunikace mezi důležitými objekty. Přitom stačí málo, obstarat si distributora.

Multithreading v C++ (ve Win32) III - OOP a vlákna

Pokračování dokumentace k Multithreading v C++ (ve Win32) - Tentokrát si povíme něco o tom jak začlenit vlákna do OOP

Šablony a kvalifikátor const - Jak správně konstruovat šablony s ukazatelem?

Chytrý ukazatel nebo pole? Vždy se jedná o šablonu, která obsahuje ukazatel na T. Přitom je třeba postihnout chování const

Efektivní alokátor malých objektů II

Pokračování seriálu Efektivní alokátor malých objektů I
Reklama: