Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Programowanie obiektowe w C

Ostatnio zmodyfikowano 2012-11-02 19:37
Autor Wiadomość
Badman
Temat założony przez niniejszego użytkownika
Programowanie obiektowe w C
» 2012-11-02 11:02:41
A jednak się da programować obiektowo w C:) przy użyciu GObject

Problem typowo uczelniany klasa Osoba i klasa Student, która dziedziczy po klasie Osoba.

Tak naprawdę klasa Osoba ma już pewną funkcjonalność ponieważ tak naprwdę dziedziczy po klasie GObject.
Na potrzeby przykładu wszystko zbite w jednym pliku

C/C++
#include <glib.h>
#include <glib-object.h>
//#include "osoba.h"
//#include "student.h"

/* _OSOBA_H_ */
G_BEGIN_DECLS

/* Makra na potrzeby obiektu Osoba */
#define OSOBA_TYPE             (osoba_get_type ())
#define OSOBA(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSOBA_TYPE, Osoba))
#define OSOBA_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), OSOBA_TYPE, OsobaClass))
#define OSOBA_IS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSOBA_TYPE))
#define OSOBA_IS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), OSOBA_TYPE))
#define OSOBA_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), OSOBA_TYPE, OsobaClass))

typedef struct _OsobaClass OsobaClass;
typedef struct _Osoba Osoba;

/* Deklaracja klasy */
struct _OsobaClass
{
    GObjectClass parent_class;
};

/* Deklaracja instacji obiektu */
struct _Osoba
{
    GObject parent_instance;
   
    /* Deklarcja składników publicznych*/
    gchar * imie;
    gchar * nazwisko;
    guint wiek;
   
};

/* Funkcja zwraca identyfikator klasy. Na potrzeby nowo tworzonego obiektu. */
GType osoba_get_type( void );

/* Publiczna "metoda" usawiająca nazwisko */
void osoba_set_nazwisko( Osoba * obj, const gchar * tekst );

G_END_DECLS
/* _OSOBA_H_ */


/* _OSOBA_C_ */
/* Właściwości jakie posiada obiekt Osoba */
enum
{
    PROP_0,
   
    PROP_IMIE,
    PROP_NAZWISKO,
    PROP_WIEK
};


/* Ala konstruktor nowo tworzonej instancji obiektu */
static void osoba_init( Osoba * osoba, gpointer g_class )
{
    osoba->wiek = 0;
    // g_print ( "INIT !\n" );
}

/* Metoda ustawiająca właściwośći obiektu */
static void osoba_set_property( GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec )
{
    Osoba * osoba;
    guint nr;
    const gchar * imie;
   
    g_return_if_fail( OSOBA_IS( object ) ); // Sprawdzenie czy przekazany objekt jest obiektem Osoba
   
    osoba = OSOBA( object );
   
    switch( prop_id )
    {
    case PROP_IMIE:
        imie = g_value_get_string( value );
        if( osoba->imie )
             g_free( osoba->imie );
       
        osoba->imie = g_strdup( imie );
        break;
       
    case PROP_NAZWISKO:
        osoba_set_nazwisko( osoba, g_value_get_string( value ) );
        break;
       
    case PROP_WIEK:
        nr = g_value_get_uint( value );
        if( osoba->wiek != nr )
        {
            osoba->wiek = nr;
        }
       
        break;
       
        default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
        break;
    }
}

/* Metoda pobierająca właściwośći obiektu */
static void osoba_get_property( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec )
{
    Osoba * osoba;
    g_return_if_fail( OSOBA_IS( object ) );
   
    osoba = OSOBA( object );
   
    switch( prop_id )
    {
    case PROP_IMIE:
        g_value_set_string( value, osoba->imie );
        break;
       
    case PROP_NAZWISKO:
        g_value_set_string( value, osoba->nazwisko );
        break;
       
    case PROP_WIEK:
        g_value_set_uint( value, osoba->wiek );
        break;
       
        default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
        break;
    }
}


/* Inicjalizacja klasy */
static void osoba_class_init( OsobaClass * klass )
{
    GObjectClass * object_class = G_OBJECT_CLASS( klass );
   
    /* Przeciążanie metod klasy nadzrzędnej G_OBJECT_CLASS */
    object_class->set_property = osoba_set_property;
    object_class->get_property = osoba_get_property;
   
    /* Instalowanie atrybutów / właściwośći */
    g_object_class_install_property( object_class,
    PROP_IMIE,
    g_param_spec_string( "imie",
    "imie-set",
    "Ustawia / pobiera imie",
    NULL,
    G_PARAM_READABLE | G_PARAM_WRITABLE ) );
   
    g_object_class_install_property( object_class,
    PROP_NAZWISKO,
    g_param_spec_string( "nazwisko",
    "nazwisko-set",
    "Ustawia / pobiera nazwisko",
    NULL,
    G_PARAM_READABLE | G_PARAM_WRITABLE ) );
   
    g_object_class_install_property( object_class,
    PROP_WIEK,
    g_param_spec_uint( "wiek",
    "wiek-set",
    "Ustawia / pobiera wiek",
    0,
    100,
    0,
    G_PARAM_READABLE | G_PARAM_WRITABLE ) );
}

/* Publiczna metoda ustawiajaca nazwisko obiektu Osoba */
void osoba_set_nazwisko( Osoba * obj, const gchar * tekst )
{
    gchar * nowy;
   
    nowy = g_strdup( tekst );
    if( obj->nazwisko )
         g_free( obj->nazwisko );
   
    obj->nazwisko = nowy;
}

/* Funkcja zwraca identyfikator klasy. Na potrzeby nowo tworzonego obiektu. */
GType osoba_get_type( void )
{
    static GType osoba_type = 0;
   
    if( !osoba_type )
    {
        static const GTypeInfo osoba_info = {
            sizeof( OsobaClass ),
            ( GBaseInitFunc ) NULL,
            ( GBaseFinalizeFunc ) NULL,
            ( GClassInitFunc ) osoba_class_init,
            NULL,
            NULL,
            sizeof( Osoba ),
            0,
            ( GInstanceInitFunc ) osoba_init
        };
       
        /* Rejestracja nowego typu obiektu */
        osoba_type = g_type_register_static( G_TYPE_OBJECT, "Osoba", & osoba_info, 0 );
    }
   
    return osoba_type;
}
/* _OSOBA_C_ */


/* _STUDENT_H_ */
G_BEGIN_DECLS

/* Makra na potrzeby obiektu Student */
#define STUDENT_TYPE             (student_get_type ())
#define STUDENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), STUDENT_TYPE, Student))
#define STUDENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), STUDENT_TYPE, StudentClass))
#define STUDENT_IS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STUDENT_TYPE))
#define STUDENT_IS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), STUDENT_TYPE))
#define STUDENT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), STUDENT_TYPE, StudentClass))

typedef struct _StudentClass StudentClass;
typedef struct _Student Student;

/* Deklaracja klasy */
struct _StudentClass
{
    OsobaClass parent_class;
   
};

/* Deklaracja instacji obiektu */
struct _Student
{
    /* Nadrzędna klasą jest klasa Osoba */
    Osoba parent_instance;
   
    /* Deklarcja składników publicznych*/
    guint numer_indeksu;
   
};

/* Funkcja zwraca identyfikator klasy. Na potrzeby nowo tworzonego obiektu. */
GType student_get_type( void );

G_END_DECLS
/* _STUDENT_H_ */


/* _STUDENT_C_ */
/* Właściwości jakie posiada obiekt Student */
enum
{
    PROP_STUDENT_0,
   
    PROP_NUMER_INDEKSU
};

/* Makro, które tworzy funkcje student_get_type, pozwala zaoszczędzić na ilośći kodu.
   Pierwszy parametr rejestruje obiekt Student, drugi decyduje jak bedą sie rozpoczynać
   funkcje init i class_init, parametr OSOBA_TYPE świadzczy, że dziedziczy po obiekcie Osoba */
G_DEFINE_TYPE( Student, student, OSOBA_TYPE );


/* Wymagane przez makro G_DEFINE_TYPE */
static void student_init( Student * osoba )
{
    /* Tu można inicjować lub robić zupełnie coś innego :) */
}

/* Metoda ustawiająca właściwośći obiektu */
static void student_set_property( GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec )
{
    Student * student;
    guint nr;
   
    g_return_if_fail( STUDENT_IS( object ) );
   
    student = STUDENT( object );
   
    switch( prop_id )
    {
    case PROP_NUMER_INDEKSU:
        nr = g_value_get_uint( value );
        if( student->numer_indeksu != nr )
             student->numer_indeksu = nr;
       
        break;
       
        default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
        break;
    }
}

/* Metoda pobierająca właściwośći obiektu */
static void student_get_property( GObject * object, guint prop_id, GValue * value, GParamSpec * pspec )
{
    Student * student;
   
    g_return_if_fail( STUDENT_IS( object ) );
   
    student = STUDENT( object );
   
    switch( prop_id )
    {
       
    case PROP_NUMER_INDEKSU:
        g_value_set_uint( value, student->numer_indeksu );
        break;
       
        default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
        break;
    }
}


static void student_class_init( StudentClass * klass )
{
    GObjectClass * object_class = G_OBJECT_CLASS( klass );
   
    object_class->set_property = student_set_property;
    object_class->get_property = student_get_property;
   
   
    g_object_class_install_property( object_class,
    PROP_NUMER_INDEKSU,
    g_param_spec_uint( "indeks",
    "wiek-set",
    "ustawia_numer",
    0,
    G_MAXUINT,
    0,
    G_PARAM_READABLE | G_PARAM_WRITABLE ) );
   
   
}
/* _STUDENT_C_ */


int main( int argc, char * argv[] )
{
    Osoba * osoba;
    gchar * nazwisko, * imie;
    guint wiek, nr;
   
    Student * student;
   
    /* Inicjalizacja sytemu typów. Od wersji Glib 2.36 nie wymagane */
    g_type_init();
   
    /* Utworzenie obiektu Osoba */
    osoba = g_object_new( OSOBA_TYPE, NULL );
    /* Pobranie wartości składowych */
    g_object_get( osoba, "nazwisko", & nazwisko, "imie", & imie, "wiek", & wiek, NULL );
    g_print( "Obiekt Osoba zawiera: Nazwisko: %s, Imie: %s, wiek: %d\n", nazwisko, imie, wiek );
   
    /* Ustawienie wartości składowych wiek i imie */
    g_object_set( osoba, "wiek", 5, "imie", "Pawel", NULL );
    /* "Metoda" ustawiajaca nazwisko dla obiektów Osoba */
    osoba_set_nazwisko( osoba, "Zak" );
    /* Pobranie wartości składowych */
    g_object_get( osoba, "nazwisko", & nazwisko, "imie", & imie, "wiek", & wiek, NULL );
    g_print( "Obiekt Osoba zawiera: Nazwisko %s, Imie: %s, wiek: %d\n", nazwisko, imie, wiek );
   
    /* Utworzenie obiektu Student z ustawieniem składowej numer_indeksu */
    student = g_object_new( STUDENT_TYPE, "indeks", 16722, NULL );
    /* Pobranie wartości składowych */
    g_object_get( student, "nazwisko", & nazwisko, "imie", & imie, "wiek", & wiek, "indeks", & nr, NULL );
    g_print( "Obiekt Student zawiera: Nazwisko: %s, Imie: %s, wiek: %d, numer indeksu: %d\n", nazwisko, imie, wiek, nr );
   
    /* Ustawienie wartości składowych  imie i nzwisko */
    g_object_set( student, "imie", "Mirek", "nazwisko", "Nowak", NULL );
    g_object_set( student, "wiek", 18, NULL );
    /* Pobranie wartości składowych */
    g_object_get( student, "nazwisko", & nazwisko, "imie", & imie, "wiek", & wiek, "indeks", & nr, NULL );
    g_print( "Obiekt Student zawiera: Nazwisko: %s, Imie: %s, wiek: %d, numer indeksu: %d\n", nazwisko, imie, wiek, nr );
   
   
    return 0;
}
P-68151
DejaVu
» 2012-11-02 11:31:20
Nie ma słowa "objektowo". Pisz "obiektowo".
P-68156
Mrovqa
» 2012-11-02 11:57:05
@Badman - wiemy. Wystarczy sobie napisać tę obiektowość. Równie dobrze w assembly też możesz sobie pisać obiektowo (dowód? kompilatory jakoś to robią :P)
P-68162
Badman
Temat założony przez niniejszego użytkownika
» 2012-11-02 12:17:20
@DejaVu: na 5 minut będę pamiętał, tak samo jak z ę i e :)

@Mrovqa: Wielu wykładowców na uczelniach twierdzi inaczej !
P-68167
Mrovqa
» 2012-11-02 19:37:28
@Badman wiesz, C - tak jak assembly - nie wspiera natywnie obiektowości - czysty język tego po prostu nie ma - ale jak się postarać, to można sobie to napisać :)
@Mrovqa: Wielu wykładowców na uczelniach twierdzi inaczej !
Wielu != wszyscy; wielu to równie dobrze może być <1% :P
P-68265
« 1 »
  Strona 1 z 1