Şimdi Ara

C++ Class Virtualleri

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
7
Cevap
0
Favori
940
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • Arkadaşlar mesajım neden silindi bilmiyorum. Fakat şöyle birşey soracağım. Classlarda Extern ve Virtual arası fark nedir. Silinen mesaj çok daha uzundu ama NEDENSE silinmiş...



  • Bir kaç gündür forum kafayı yiyor, mesajları siliyor, almıyor filan. Windows ile server yaparsan, forum koyarsan böyle olur işte, paranla madara olursun, herneyse..

    Virtual ile extern'in alakası yok. Extern, derleyiciye "bu kodun dışında bir yerlerde, şöyle şöyle bir sembol var." şeklinde bir belirtimde bulunur. Derleyici, bu sembolün bir yerlerde var olduğunu kabul eder ve verilen tanıma göre o sembolü kullanmanıza izin verir. Ve linker için, bu sembolün referansını kodun içine boy pos bilgisiyle yerleştirir. Böylece linker, statik veya dinamik olarak, bu sembolü bulunduğu yere koyar.

    Pratikte bu, kullandığınız kütüphane, bir diğer C kodunun derlenmiş hali olan obj. dosyası (object, nesen değil, obj dosyası) içindeki bir değişkeni, fonksiyonu, yani bellekte olan bir şeyi kullanabilmenizi sağlar.

    Virtual ise, bir OOP terimidir. Bu, mevzubahis nesneden türeyen diğer nesnelerin bu fonksiyonun üzerien yazabilecekleri anlamına gelir. C++ bu işi otomatik yapar. Bu dispatch tablosu denen bir yöntemle sağlanır. Basitçe, her elemanı bir fonksiyonu gösteren bir tablo, array düşünün. Derleyici, bu arraya istenen fonksiyonun adresini koyar ve onu kullanır. Siz, uygulama çalışırken bu array'ı (tabloyu) değiştirip, oradaki orjinal fonksiyon yerine kendinizinkini koyabilirsiniz.

    Bu mevzu, C++ için, "virtual function" tabiriyle terimleşmiştir. C++, bu gibi üzerine yazılabilecek fonksiyonlar için class yapısında özel bir tablo tutar. Buna vtbl denir. Nesne (instance'ı) oluşurken, bu tabloya orjinal fonksiyonu koyar. Bunu her yeni inherited, yani o nesneden türeyen nesne tekrar edeceği için, uygulama en son yazılan, yani en sondaki nesneye dair fonksiyonu çağırmış olacaktır.

    Çok kabaca özetlediğimiz bu alt düzey mekanizmalardan gayrı söylemek gerekirse... Virtual fonksiyon, bir nesne içinde, o nesneden türeyen diğer nesneler tarafından kendi özel fonksiyonları ile değiştirilebileceği fonksiyonlardır.

    Basitçe bir örnek verelim:

     
    class bomba {
    public:
    void hede() {}
    virtual void patla() {}
    };

    class dinamit: public bomba {
    public:
    virtual void patla() {}
    }

    class catapat: public bomba {
    public:
    virtual void patla() {}
    }

    catapat::patla() { ses_cikar("çaaat, pıt, pat"); }
    dinamit::patla() { ses_cikar("Brooomm"); }

    bomba *bomb1 = (bomba *) new catapat();
    bomba *bomb2 = (bomba *) new dinamit();


    Şimdi, bomb1 ve bomb2, bomba nesnesinden türediği için, patla() metoduna sahip. Aynı vtbl vs. gibi altyapıya sahip şeyler. Eğer bomb1->patla() derseniz, catapat::patla() çağrılır. Diğeride aynı şekilde.

    Böylece siz temel özellikleri verip, bu özelliklere göre gereken ekstra fonksiyonları ekleyebilirsiniz. Örneğin, ekrana bir şeyler koyacaksınız diyelim.

    quote:

    class widget: {
    public:
    int enable(); // Aktif mi,
    int show(); // Göster..
    int text(char *txt); // Üzerine yazan
    virtual int click(); // Fare tıkladı..
    };

    class button: public widget {
    public:
    virtual int click();
    };

    class textentry: public widget {
    public:
    virtual int click();
    };

    button::click() {
    //butona basılınca içeri gitsin, sonra geri çıksın bunun kodu.
    }

    textentry::click() {
    //focus etsin, mevcut texti seçsin vs. bunun kodu..
    }



    Böylece, göster, enable et, boyutla vs. gibi bir sürü ortak fonksiyonu alttaki widget nesnesi hallederken, siz üzerien yazdığınız click() fonksiyonları ile özel aksiyonlaır yapabilir olursunuz. Bir diğer faydası ise, widget nesnesini bilen herkesin (kodunuzdaki diğer fonksiyonlar vs.) bu bir button, düğmemi yoksa text giriş kutusu mu bilmeden, widget'in bu özelliğini bilerek kullanabilmesidir.

    Bu örneğin, sizin ne koyduğunuzu bilmeyen menü kodunuz için faydalı bir özelliktir. Sağ tuşa basınca, widget'ın "right_click()" çağrısını yapar. Onun düğmemi, text kutusu mu ne olduğuyla ilgilenmez, mesela.. Bu da kod yazmayı ve daha önceden yazılmış kodu kullanmayı son derece kolaylaştırır.




  • Bu konuda benim de bir sorum olacak.
    Normal fonksiyonlarda, derleyici fonksiyon çağırma bilgisini derleme anında elde edip kodu oluşturabiliyor. Fakat virtual fonksiyonlarda bu iş çalışma zamanında yapılıyor.
    Acaba fonksiyon kodu çalışmaya başlayıncaya kadar geçen süre normal ve virtual fonksiyonlarda ne kadar fark eder? Yani olur olmadık yerde virtual fonksiyon kullansak programı gözle görülür şekilde yavaşlatırmıyız?
  • quote:

    Normal fonksiyonlarda, derleyici fonksiyon çağırma bilgisini derleme anında elde edip kodu oluşturabiliyor.


    Derleyicinin nasıl yoğurt yiyeceğini kendisi bilir, ama bu pek öyle olmaz.

    Genelde bir şeyler unutulur, kimse bilmez, önemsemez. C# veya Java için bunu bilmek zaten abesle iştigaldir ama, bir programcının buna hakim olması elzemdir: Linker.

    Derleyici, fonksiyonların nerde, nasıl olacağını bilmez (bilmemelidir, öylesi iyidir). Bu, uygulama çalıştırıldığında linker tarafından gerçekleştirilir. Derleyici, obj kodunda semboller tanımlar. İçeriği bir şey olabilir, önemli değil. int, pointer, float, buffer vs. Linker bunun boyu ile ilgilenir. Derleyici bu sembollere bir referans yapar. Yani kodun içine direk olarak fonksiyonun adresine sıçrayan bir kod koymaz. Bunun yerine talbodaki adresin içindeki yere sıçramasını söyleyen bir kod koyar.

    Linker, bu tabloyu oluşturur. Böylece, kütüphane, dll, shared object vs. neyse artık, içindeki koda, başka kod içinden sıçramak veya erişmek mümkün olur.

    Buna aslen "relocation" denir. Linker, kod bloklarının yerini değiştirebilir, evirip çevirebilir. Çalışma zamanında dahi bunu yapabilir aslen. Yani, fonksiyon, değişken vs. adresleri dinamik olarak yönetilir.

    Eğer siz bir fonksiyona static derseniz, bu o fonksiyonun (yada değişkenin vs.) relocate edilmeyeceği anlamını taşır. Derleyicinin bunu yapmak için elindeki tek koz, o sembolü linker gizlemektir. Linkerin bakıp bu sembol aha burada, öbürü şurada diyeceği bu tabloya o sembolü koymazsanız, haliyle o obj, yani dosya dışından o sembolü görmek imkansız olacaktır.

    Ama gördüğünüz gibi, static terimi, aslen koddaki bir sembolü (fonksiyon, sayı, değişken vs.) diğer kodlardan saklamak değil, dinamik olarak yerinin değişip durmasını engellemek için kullanılıyormuş.

    Bunun bir diğer yan etkisi de şudur. Yeri değişip durmayan bir şey, elbetteki sürekli sabit değer taşıyacaktır. Yani bir fonksiyon içinde bir değişkene static derseniz, o da yeri, adresi vs. değişmemek üzere, sabit bir yere konacaktır. ama demezseniz, her fonksiyona girişte yeniden o değişkene dair adres belirlenir, oluşturulur.

    Gördüğünüz gibi, bu terimlerin aslında altında yatan kavramlar çok farklı aslında.

    Ve gene gördüğünüz gibi, fonksiyon adresleri bir tabloda tutuluyor, birisi statik diyerek onu fiks etmediği sürece. Ve bu tablo, derleme zamanında değilde, aslen çalıştırma zamanında linker tarafından dolduruluyor. Teorik olarak bu tablo çalışma zamanında da düzenlenebilir. Fakat bu macera hevesine 10 bin metreden paraşütsüz atlamak gibi bir şey olur: Felaket kaçınılmazdır.

    Şimdi bu olay, yani geç bağlaşım/bağlama, aslen C veya C++'nın bir hedesi değil. BU işletim sistemlerinin getirdiği bir şey. C/C++'da onların koyduğu bu kurallara göre bu işi böyle yapıyor. Bu yüzden adettir, her işletim sistemi beraberinde linker denen şeyi barındırır. DOS bile, o bir tek 360KB disketinde bir linker bulundururdu mesela..

    Mesela DSP'ler vs. içinde linkerler mevcuttur. Windows ve Linux içinde, OS/2 içinde.

    Kısaca bu mevzu o kadar basit değildir. Biraz daha düşündüğünüzden farklıdır.

    quote:

    Yani olur olmadık yerde virtual fonksiyon kullansak programı gözle görülür şekilde yavaşlatırmıyız?


    Eğer şöyle bir şey yazarsanız:

    while (1) { call virtual_function(); i++; }

    Bu kodu 1 sn. çalıştırırsanız, virtual funk. kullanınca i'nin son değerinin ciddi şekilde daha küçük olduğunu görürsünüz. Fakat bunun sebebi, zaten kodun fonksiyon çağırmaktan başka hiç bir işinin olmamasıdır. Klasik bir programda, fonksiyon çağırma kodunun overhead'ı, yani sisteme yükü yüzde bir, binde bir bile olmaz, çok çok küçük bir değere tekabül eder. Bu nedenle, fonksiyon çağırma yükünün getireceği yük önemsenecek bir şey değildir.

    Velakin yüksek hız gerektiren şifreleme, veri transfer, modülasyon vs. gibi işlevlerde, bu yük çok anlamlı olabilir. O gibi programlarda static fonksiyon kullanmak, inline fonksiyon, hatta tamamen assembler ile işe girişmek gibi özel çözümler uygulanır. Fakat bir ayağı fare veya ekranda olan, diskte olan bir kodun bu kadar tribe ihtiyacı olmaz.

    Performans konusunda mesele genel olarak bottleneck meselesidir. Yani kodun bir yerlerinde bir şey tüm akışı yavaşlatmaktadır. Bu darboğazı aşınca, kodda zincirinden kurtulur, coşar gider. Bu gibi darboğazlar oluşturmaktan kaçındığınız sürece, performans sorun olmaz.

    Ama elbette bazı darboğazlardan kaçılamaz: Yavaş bir serverden bilgi beklemek mesela..



    < Bu mesaj bu kişi tarafından değiştirildi skoylu -- 13 Nisan 2010; 22:15:13 >




  • Eyvallah sağolun. Şu server olayı bugün hakikaten canımı sıktı açılmıyor site arkadaş!
    Microsoft ole db error.
  • skoylu, ilk önce sorularımı cevapladığınız için çok teşekkür ederim. Fakat bir sorum olacak...


    Direct3D gibi bir API ye geçiş yapmak istiyorum. Fakat C++ bilgilerimde Upcast, Downcast gibi Polymorphisim olayları, Multiple Inheritance ve basit STL bilgisi eksiklerim var. Buna devam etmeden önce ne yapmalıyım. Tamam bunları tamamladım diyelim. Fakat Direct3D gibi bir API ye geçmek için yeterli bilgiye sahip olur muyum? Yoksa birkaç kitaptaki egzersiz bölümlerini mi yapayım kendimi geliştirmek için? Sizin çoğu kişiye bir programı incelemeyi önerdiğinizi duydum fakat hangi programı inceleyeceğimi dahi bilmiyorum. Bu konularda bana yardım edebilirseniz çok teşekkür ederim.
  • quote:

    Fakat C++ bilgilerimde Upcast, Downcast gibi Polymorphisim olayları, Multiple Inheritance ve basit STL bilgisi eksiklerim var.


    İnan benimde var. Hala struct, public vs. filan yazarken kitabı vs. açar bakarım. Hoş, bin kere bakmışımıdır belki daha önce ama olsun.

    Direct3D gibi bir API'ye geçmenin hiç bir zorluğu yok. Ona geçmek için bilmen gereken STL filan değil. Sadece oturup geçmen. Evet, otur, biraz uğraş, zaten ne gerekiyorsa, önüne çıkacak, seni onu öğrenmeye iteleyecektir.
  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.