C ile OOP, polymorphism uygulaması

cemalb

Üye
Katılım
9 Eki 2019
Mesajlar
126
Puanları
1
C dilinde polymorfizm uygulama hakkında bilgisi olan var mı?
Yabancı kaynaklardan örnekler buldum ama tam anlamadığım için kafama bir kaç soru takıldı. . .
 
Anlayamadıklarınızı sorun, yardımcı olmaya çalışalım.
 
Aşağıda Pdf paylaşacağım. Oradan öğrendim konuyu. Ayrıntılı bakmak isteyen olursa sf 10'dan itibaren polimorfizm konusu işlenmiş, bakılabilir. Ben örnek kodlar ile izah etmeye çalışayım, sorumu da öyle sorarım. Biraz uzun olacak malesef ama konu ile ilgilenen arkadaşlara fikir vermesi açısından güzel olacağını düşünüyorum.

Örneğin "şekil" isminde bir Class olacak. Alan ve uzunluk hesabı için 2 adet metotu olacak. Bu class'tan türeyen "dörtgen" ve "daire" class'ları bu metotları kullanarak kendine özel alan ve uzunluk hesabı yapacak. (override)

sekil.h dosyamız:
C:
struct Vtable;        //deklarasyon yaptık.

typedef struct{        //Şekil Super Class'ı
    struct Vtable const* vptr; //"Vtable" türünden pointer tanımladık. Override ederken kullanacağız
    uint16_t x;
    uint16_t y;

}Shape;

struct Vtable {    //Alt sınıflardaki ortak metotlar. Fonksiyon pointer olarak Vtable yapısında tanımlanır.
    void(*area)(Shape const* const me);
    void(*lenght)(Shape const* const me);
};

void shape_ctor(Shape* me, int x, int y);

**C++ da class içinde fonksiyon tanımlayabiliyorduk. C de bunu taklit ederken ise fonksiyon pointerları kullanıyoruz. Shape yapısında "area" ve "lenght" fonksiyonları için fonksiyon pointer tanımladık. Ama bu fonksiyon pointerlarını direkt tanımlamak yerine önce Vtable'da tanımladık, sonra Vtable türünden bir pointer kullanarak dolaylı olarak Shape Classında tanımladık. Bu da ileride işimize yaracak. Alt sınıflar için bu fonksiyonların gövdesini farklı yazmamıza olanak sağlayacak.

sekil.c dosyamız:
C:
void shape_ctor(Shape* me,int x, int y) { //constructor metotu. ilk değerleri veriyoruz.
    me->x    = x;
    me->y    = y;
}


rect.h dosyası:
C:
#include "shape.h"

typedef struct  {
    Shape super;    //Super Class'tan miras almamızı sağlıyor.
    uint16_t en;  
    uint16_t boy;    //rect sınıfının kendine ait özellikleri
}rect;

void rect_ctor(rect* me, uint16_t x, uint16_t y, uint16_t en, uint16_t boy);

rect.c dosyası:
C:
void rect_lenght(void* me);
void rect_area(void* me);        //private olması için burda tanımladık

//constructor
void rect_ctor(rect* me,uint16_t x, uint16_t y, uint16_t en, uint16_t boy) {
    //burada rect'a ait metotlar vtbl'ye verildi.
    struct Vtable vtbl = { &rect_area, &rect_lenght };
   
    shape_ctor(&me->super, x, y);
    me->super.vptr = &vtbl;            //override vptr. area ve lenght metotları rect'e ait metotlara işaret ediyor.
    me->en  = en;
    me->boy = boy;
}


void rect_lenght(void* me) {
    rect* me_ = (rect*)me;        //downcast işlemi
    printf("rectangle lenght: %d\n",(me_->en + me_->boy) * 2);
}
void rect_area(void* me) {
    rect* me_ = (rect*)me;        //downcast işlemi
    printf("rectangle area: %d\n", (me_->en)*(me_->boy));
}

"circle.h" ve "circle.c" dosyalarıda aynı mantık ile yazılır;

circle.h:
C:
#include "shape.h"

typedef struct {
    Shape super;
    uint16_t radius;
}circle;

void circle_ctor(circle* me, uint16_t x, uint16_t y, uint16_t r);

circle.c:
C:
void circle_lenght(void* me);
void circle_area(void* me);

void circle_ctor(circle* me, uint16_t x, uint16_t y, uint16_t r) {
    struct Vtable vtbl = {&circle_area,&circle_lenght};

    shape_ctor(&me->super, x, y);
    me->super.vptr = &vtbl;
    me->radius = r;
}

void circle_lenght(void* me) {
    circle* me_ = (circle*)me;
    printf("circle lenght: %f\n", (me_->radius) * (2) * (3.14));
}
void circle_area(void* me){
    circle* me_ = (circle*)me;
    printf("circle area: %f\n", (me_->radius) * (me_->radius) * (3.14));
}

main.c:
C:
#include <stdio.h>
#include "rect.h"
#include "circle.h"

int main() {
    rect  k1;
    circle d1;    //nesneleri oluşturduk.

    rect_ctor(&k1, 10, 10, 15, 20);
    circle_ctor(&d1, 10, 10, 5);        //ilk değerler verildi ve her nesne artık kendine ait
                                        //"area" ve "lenght" metotuna işaret ediyor.

    k1.super.vptr->area(&k1);
    d1.super.vptr->area(&d1);
//iki nesne de aynı metotu çağırdı ama ikisi için farklı hesaplama yapılacak.
}

Şimdi ilk sorum şu:
Bu kodu çalıştırınca hata alıyorum. "d1.super.vptr->area(&d1);" satırında "Exception thrown: read access violation. d1.super.vptr was 0xFFFFFFFFFFFFFFFF." diye uyarı veriyor.
Sonra stackoverflow'da araştırdım. rect.c ve circle.c 'de constructor'da "struct Vtable vtbl = {...}" satırını "static const struct Vtable vtbl = {...}" şeklinde yapınca hatasız çalıştı.. static ekleyince ne oldu da çalıştı? önceden niye hata veriyordu ?
 

Ekli dosyalar

  • AN_OOP_in_C.pdf
    881 KB · Görüntüleme: 1
Son düzenleme:
Kodları detaylı incelemeye vaktim olmadı. Ancak sorunuzun cevabını bu şekilde bulabilirsiniz.
“One Definition Rule”
İyi çalışmalar.
 

Yeni mesajlar

Forum istatistikleri

Konular
127,964
Mesajlar
913,939
Kullanıcılar
449,609
Son üye
cherrywine

Yeni konular

Geri
Üst