Czy klasy są dostępne w klasycznym języku C ?

0

Głupie pytanie tak jak w temacie, czy korzystając z klas wciąż pisze jeszcze w C czy to już C++ ? :)

4

Gdybyś użył kompilatora C to być od razu wiedział.

Język C nie zawiera składni do definiowania klas.

5

Natomiast można klasy gorzej lub lepiej symulować. Programowanie zbliżone do obiektowego jest w C możliwe.

0

Zakładam że będzie to jakieś sprytne sklejenie kilku struktur, prawda ? :)

1

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

2

http://ideone.com/Kb43wr
tu przykład. Kod nie mój. Imo można to jeszcze sprytniej zrobić.

3

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.

0

Z innych przykładów:

I to nie będzie symulowanie, a pełnoprawna obiektowość, identyczna w funkcjonalności z C++.

1 użytkowników online, w tym zalogowanych: 0, gości: 1