Głupie pytanie tak jak w temacie, czy korzystając z klas wciąż pisze jeszcze w C czy to już C++ ? :)
Gdybyś użył kompilatora C to być od razu wiedział.
Język C nie zawiera składni do definiowania klas.
Natomiast można klasy gorzej lub lepiej symulować. Programowanie zbliżone do obiektowego jest w C możliwe.
Zakładam że będzie to jakieś sprytne sklejenie kilku struktur, prawda ? :)
nie rozumiem pytania. jezyk C jest jezykiem strukturalnym (?) czyli pisanie obiektowo odpada (mam nadzieje ze kaczor tu sie nie pojawi :D). mozna pisac w C++ i uwazac ze sie juz pisze obiektowo ale napisanie jednej klasy w kodzie raczej nie nazwalbym kodu obiektowego
http://ideone.com/Kb43wr
tu przykład. Kod nie mój. Imo można to jeszcze sprytniej zrobić.
Podam przykład rzeczywisty, zamiast wydumanego: klasy COM w WinAPI.
Tak wygląda odtwarzanie pliku MP3 z wykorzystaniem wbudowanej w Windows biblioteki DirectShow i smartpointerów z ATL:
#include <atlbase.h>
#include <atlstr.h>
#include <dshow.h>
struct CCoInitialize
{
CCoInitialize() { CoInitialize(nullptr); }
~CCoInitialize() { CoUninitialize(); }
} init;
int main()
{
CComPtr<IGraphBuilder> gb;
gb.CoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER);
CComQIPtr<IMediaControl> mc = gb;
CComQIPtr<IMediaEvent> me = gb;
gb->RenderFile(L"muza.mp3",nullptr);
mc->Run();
long dummy;
me->WaitForCompletion(INFINITE, &dummy);
}
Mamy tu kilka wywołań metod, obiekty same się zwolnią dzięki smarpointerowi CComPtr
, drugi CComQIPtr
wykonuje przy okazji pewnego rodzaju rzutowanie (konwersję typu).
A teraz sam program w C:
#define COBJMACROS
#include <dshow.h>
int main()
{
IGraphBuilder *gb;
IMediaControl *mc;
IMediaEvent *me;
long dummy;
CoInitialize(NULL);
CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (LPVOID*)&gb);
IGraphBuilder_QueryInterface(gb, &IID_IMediaControl, (LPVOID*)&mc);
IGraphBuilder_QueryInterface(gb, &IID_IMediaEvent, (LPVOID*)&me);
IGraphBuilder_RenderFile(gb, L"muza.mp3", NULL);
IMediaControl_Run(mc);
IMediaEvent_WaitForCompletion(me, INFINITE, &dummy);
IMediaEvent_Release(me);
IMediaControl_Release(mc);
IGraphBuilder_Release(gb);
CoUninitialize();
}
Tu trzeba więcej rzeczy zrobić ręcznie: dochodzą nam Release i QueryInterface, co załatwiały nam w C++ smartpointery.
Składnia wywołania „metody” zmienia się z obiekt->metoda(...)
na typ_metoda(obiekt, ...)
. W C++ obiekt na rzecz którego metoda jest wywoływana jest przekazywany jako niejawny parametr this
do metody. W C musimy zrobić to sami.
Microsoft przewidział też drugą konwencję używania obiektów COM w C:
#include <dshow.h>
int main()
{
IGraphBuilder *gb;
IMediaControl *mc;
IMediaEvent *me;
long dummy;
CoInitialize(NULL);
CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (LPVOID*)&gb);
gb->lpVtbl->QueryInterface(gb, &IID_IMediaControl, (LPVOID*)&mc);
gb->lpVtbl->QueryInterface(gb, &IID_IMediaEvent, (LPVOID*)&me);
gb->lpVtbl->RenderFile(gb, L"muza.mp3", NULL);
mc->lpVtbl->Run(mc);
me->lpVtbl->WaitForCompletion(me, INFINITE, &dummy);
me->lpVtbl->Release(me);
mc->lpVtbl->Release(mc);
gb->lpVtbl->Release(gb);
CoUninitialize();
}
Wywołanie metody to obiekt->lpVtbl->metoda(obiekt, ...)
. Nie musimy pisać mozolnie typu każdego obiektu, ale nazwę obiektu trzeba podać dwa razy. lpVtbl
to zawarty w każdym obiekcie wskaźnik na tablicę metod.
Z innych przykładów:
I to nie będzie symulowanie, a pełnoprawna obiektowość, identyczna w funkcjonalności z C++.