+ Cevap Yaz
Toplam 6 sayfadan 2. sayfa
İlkİlk 1 2 3 4 5 6 En SonEn Son
57 sonuçtan 11 ile 20 arası gösteriliyor

Konu: dev c++'ı nasıl bilirsiniz?

  1. #11
    Ali Çehreli
    Üyelik Tarihi
    10/2002
    Mesaj
    2,901

    Alıntı _Onk@_, mesajından alıntı: Mesajı Gör
    Yukarıdaki gösterim bence oldukça kafa karıştırıcı.
    İlkleme listesinin kullanılmasının geçerli nedenleri var. Ayrıca bana kafa karıştırıcı gelmiyor.

    Onun yerine ben kurucu işlevin içine yazmayı tercih ediyorum.
    Yani şöyle diyorsun:

    Kod:
        Dikdortgen(double en, double boy)
        {
            en_ = en;
            boy_ = boy;
        }
    
    O işlemler ilkleme değil, atamadır. Atama iki işlemden oluşur: var olan değerin sonlandırılması ve yeni değerin kopyalanması. int gibi temel türden olan üyelerde bunun önemi yok tabii ama sınıfların çoğu üyesi başka türlerdendir.

    Atamanın iki alt işlemden oluştuğunu vurguladıktan sonra bakabiliriz:

    1) atanamayan türlerde çalışmaz

    1a) örneğin referans üyelerde çalışmaz; referansların bir kere ilklenmeleri gerekir; atama işlemi de zaten referansın "gösterdiği" nenseyi değiştirir. Örneğin en_ bir 'int&' olsaydı yukarıdaki kurucu çalışmazdı

    1b) operator= işleçleri iptal edilmiş olan bir çok kullanıcı türü vardır: örneğin boost::scoped_ptr; yukarıdaki kurucu onlarla da çalışmaz

    2) kurucu işlevin { parantezinden içeri girildiği an bütün üyeler ya ilklenmişlerdir, ya da o fırsat kaçmıştır

    2a) Örneğin std::string türünden bir üye zaten boş olarak ilklenmiştir. Atama işlemi gereksizce zaman harcar

    2b) (Bu tamamen teorik) Yukarıdaki en_ ve boy_, atama işleminde "hiç ilklenmeden" kullanılmaktadırlar. Dil standardının gözünde bu tanımsız davranıştır

    ':' karakteri switch ifadelerinde, üçlü operatörde ve etiketlerde kullanılıyor. Bence '*' gibi anlam karmaşasına neden oluyor.
    Katılıyorum. C++ dili, o güne kadar yazılmış C programlarının çok az değişiklikle derlenebilmelerini hedeflediği için olabildiğince az işleç ve olabildiğince az anahtar sözcük getirmeye çalışmıştır.

    Belki de : karakterini o yüzden düşünmüşlerdir.

    Neyse benim aklıma öyle ilklendirmek gelmediği için daha fazla çamur atmayayım
    Çamur atmakta hiçbir sakınca yok. Gösterdiğin nedenler geçerli ama ilkleme listesinin neden gerekli olduğunu da hatırlamak gerek.

    Ali

  2. #12
    c3r
    c3r şu an hatta
    Usta olmak istiyorum c3r Adlı Üyenin Profil Grafiği
    Üyelik Tarihi
    11/2008
    Yer
    Monitörün karşısı
    Mesaj
    908

    Alıntı acehreli, mesajından alıntı: Mesajı Gör
    İlkleme listesinin kullanılmasının geçerli nedenleri var. Ayrıca bana kafa karıştırıcı gelmiyor.



    Yani şöyle diyorsun:

    Kod:
        Dikdortgen(double en, double boy)
        {
            en_ = en;
            boy_ = boy;
        }
    
    O işlemler ilkleme değil, atamadır. Atama iki işlemden oluşur: var olan değerin sonlandırılması ve yeni değerin kopyalanması. int gibi temel türden olan üyelerde bunun önemi yok tabii ama sınıfların çoğu üyesi başka türlerdendir.

    Atamanın iki alt işlemden oluştuğunu vurguladıktan sonra bakabiliriz:

    1) atanamayan türlerde çalışmaz

    1a) örneğin referans üyelerde çalışmaz; referansların bir kere ilklenmeleri gerekir; atama işlemi de zaten referansın "gösterdiği" nenseyi değiştirir. Örneğin en_ bir 'int&' olsaydı yukarıdaki kurucu çalışmazdı

    1b) operator= işleçleri iptal edilmiş olan bir çok kullanıcı türü vardır: örneğin boost::scoped_ptr; yukarıdaki kurucu onlarla da çalışmaz

    2) kurucu işlevin { parantezinden içeri girildiği an bütün üyeler ya ilklenmişlerdir, ya da o fırsat kaçmıştır

    2a) Örneğin std::string türünden bir üye zaten boş olarak ilklenmiştir. Atama işlemi gereksizce zaman harcar

    2b) (Bu tamamen teorik) Yukarıdaki en_ ve boy_, atama işleminde "hiç ilklenmeden" kullanılmaktadırlar. Dil standardının gözünde bu tanımsız davranıştır



    Katılıyorum. C++ dili, o güne kadar yazılmış C programlarının çok az değişiklikle derlenebilmelerini hedeflediği için olabildiğince az işleç ve olabildiğince az anahtar sözcük getirmeye çalışmıştır.

    Belki de : karakterini o yüzden düşünmüşlerdir.



    Çamur atmakta hiçbir sakınca yok. Gösterdiğin nedenler geçerli ama ilkleme listesinin neden gerekli olduğunu da hatırlamak gerek.

    Ali
    kazanan benim c++ öğrenmemde yardımcı olma şansını yakayacaktır şaka bir yana _onk@_ ve acehrili gibi tecrübeli büyüklerimizin olması bizim için çok faydalı oluyor

  3. #13
    Ziraat Mühendisi _Onk@_ Adlı Üyenin Profil Grafiği
    Üyelik Tarihi
    09/2008
    Yer
    Ankara
    Mesaj
    713

    Alıntı acehreli, mesajından alıntı: Mesajı Gör
    İlkleme listesinin kullanılmasının geçerli nedenleri var. Ayrıca bana kafa karıştırıcı gelmiyor.
    Tamamen tecrübe ile alakalı bir şey sanırım. Hala kafa karıştırıcı benim için. Belki standart kabul edilen her sınıf için bir cpp bir h dosyası kullanmak sorunu çözer Emin değilim

    Bora Güngören'e göre yapıcı işlev içindeki atama sizin gösterdiğiniz biçimde yorumlanır (eğer derleyici başarabiliyorsa). Her halükarda sorun çıkmayacağı için bence okunabilirliği kolay olan yazım tercih edilmelidir. Tabi benimkisi fikir. Mingw'yi düzelttikten sonra savımı destekleyecek ya da çürütecek deneylere başlayacağımdan emin olabilirsiniz

    Alıntı acehreli, mesajından alıntı: Mesajı Gör
    Katılıyorum. C++ dili, o güne kadar yazılmış C programlarının çok az değişiklikle derlenebilmelerini hedeflediği için olabildiğince az işleç ve olabildiğince az anahtar sözcük getirmeye çalışmıştır.

    Belki de : karakterini o yüzden düşünmüşlerdir.
    İşleç karışıklığı C ve C++'ın eleştirilen yönlerinden sadece bir tanesi. Fakat yerden yere vurulsa da vazgeçemiyoruz

  4. #14
    Ali Çehreli
    Üyelik Tarihi
    10/2002
    Mesaj
    2,901

    İlkleme listesinin bir nedenini unutmuşum:

    3) Bazı türlerin varsayılan kurucuları yoktur. O türden üyelerin ilkleme listesinde kurulmaları gerekir.

    Alıntı _Onk@_, mesajından alıntı: Mesajı Gör
    savımı destekleyecek ya da çürütecek deneylere başlayacağımdan emin olabilirsiniz
    Bu konuda yardımcı olsun diye bir program aşağıda. Deneme adlı sınıfın kurucusunu senin söylediğin gibi yazmaya çalış. Üyelerden yalnızca pahalidir_ ismindekini kurucunun içine alabilirsin, o da benim ufak bir hilem nedeniyle 100 megabaytlık bir dosya oluşturacağı için yavaş olacaktır.

    Kod:
    #include <fstream>
    
    using namespace std;
    
    class Atanamaz
    {
        int i_;
    
        Atanamaz(const Atanamaz &);
        Atanamaz & operator= (const Atanamaz &);
    
    public:
    
        explicit Atanamaz(int i)
            :
            i_(i)
        {}
    };
    
    class KurucusuParametreAlir
    {
        int i_;
    
    public:
    
        explicit KurucusuParametreAlir(int i)
            :
            i_(i)
        {}
    };
    
    /*
     * Hile yapiyorum: Yalnizca varsayilan kurucusu pahali olan
     * fazla tUr yoktur.
     */
    class VarsayilanKurucusuPahalidir
    {
        int i_;
    
    public:
    
        VarsayilanKurucusuPahalidir()
            :
            i_(0)
        {
            ofstream dosya("deneme_dosyasi.txt");
    
            for (int i = 0; i != 100000000; ++i) {
                char karakter = (i % 96) + 32;
                dosya << karakter;
            }
        }
    
        explicit VarsayilanKurucusuPahalidir(int i)
            :
            i_(i)
        {}
    };
    
    class Deneme
    {
        int & referans_;
        Atanamaz atanamaz_;
        KurucusuParametreAlir parametreAlir_;
        VarsayilanKurucusuPahalidir pahalidir_;
    
    public:
    
        explicit Deneme(int & i)
            :
            referans_(i),
            atanamaz_(1),
            parametreAlir_(2),
            pahalidir_(3)
        {}
    };
    
    int main()
    {
        int i = 42;
        Deneme deneme(i);
    }
    
    Ali

  5. #15
    Ziraat Mühendisi _Onk@_ Adlı Üyenin Profil Grafiği
    Üyelik Tarihi
    09/2008
    Yer
    Ankara
    Mesaj
    713

    Ali Hocam ilklendirme listesi hakkında söylediklerinizin hepsine katılmakla birlikte alışkın olduğum yazım şekline göre Deneme sınıfını değiştirdim.
    Kod:
    class Deneme
    {
       int * referans_; //& referans_; madem referansı sınıf içinde ilklendiremiyoruz, gösteririz
        Atanamaz* atanamaz_;
       KurucusuParametreAlir* parametreAlir_;
        VarsayilanKurucusuPahalidir* pahalidir_;
    
    public:
    
        explicit Deneme(int & i)
    	{
            referans_=&i;
            atanamaz_=new Atanamaz(i);
            parametreAlir_=new KurucusuParametreAlir(i);
            pahalidir_=new VarsayilanKurucusuPahalidir(i);
        }
    };
    
    Açıkçası kötü niyetli bir sınıf oldu fakat sonuçta beklendiği gibi hata vermeden derlenip çalışıyor. En azından derlemeden sonra bir sınıfın ne kadar alan gerektireceğinden eminiz o yüzden sınıfı gösteren işaretçilerin kullanılmasında sakınca olduğunu düşünmüyorum.

  6. #16
    Ali Çehreli
    Üyelik Tarihi
    10/2002
    Mesaj
    2,901

    Alıntı _Onk@_, mesajından alıntı: Mesajı Gör
    Ali Hocam ilklendirme listesi hakkında söylediklerinizin hepsine katılmakla birlikte alışkın olduğum yazım şekline göre Deneme sınıfını değiştirdim.
    Ama yine de bu işin alışkanlıkla değil, gereklilikle ilgili olduğunda hemfikiriz.

    Kod:
    class Deneme
    {
       int * referans_; //& referans_; madem referansı sınıf içinde ilklendiremiyoruz, gösteririz
        Atanamaz* atanamaz_;
       KurucusuParametreAlir* parametreAlir_;
        VarsayilanKurucusuPahalidir* pahalidir_;
    
    public:
    
        explicit Deneme(int & i)
    	{
    
    Bu noktada o üyelerin hiçbirisi ilklenmedikleri için en azından kurucu içinde rastgele değerlerine erişmek gibi bir risk var. O yüzden yine de önce şöyle yapılmalıdır:

    Kod:
        explicit Deneme(int & i)
                :
                referans_(NULL),
                atanamaz_(NULL),
                parametreAlir_(NULL),
                pahalidir_(NULL)
    	{
    
    Ondan sonra seninki gibi:

    Kod:
            referans_=&i;
            atanamaz_=new Atanamaz(i);
            parametreAlir_=new KurucusuParametreAlir(i);
            pahalidir_=new VarsayilanKurucusuPahalidir(i);
        }
    };
    
    1) Atanamaz nesnesinin başarıyla kurulduğunu kabul edelim. Ondan sonra KurucusuParametreAlir veya VarsayilanKurucusuPahalidir nesneleri kurulurken atılabilecek bir hata, atanamaz_'ın kaynaklarının kaybedilmelerine neden olur.

    Deneme'nin sonlandırıcı işlevindeki delete'ler işletilmezler; çünkü sonlandırıcı işlev, kurulmamış bir nesne için çağrılmaz. (Hata atılırsa Deneme nesnesi kurulamamıştır.)

    O yüzden, eğer bu yöntem uygulanacaksa üyelerin RAII'ye uygun olarak akıllı gösterge olmaları gerekir.

    Yani her üyenin maliyeti tek bir gösterge kadar değil, ayrıca akıllı göstergenin örneğin referans sayacı kadar daha artmış olur. (Eğer boost::shared_ptr kullanılacaksa, referans sayacını dinamik bellekten almak zorunda olduğu için hız olarak da maaliyetlidir.)

    2) Şimdi Deneme'nin kopyalayıcısı ve atama işleci de yazılmak zorunda kalacak. Onları da doğru olarak tanımlamamız gerekecek. Olay karmaşıklaştı ve bu yüzden tasarım daha riskli hale geldi.

    Açıkçası kötü niyetli bir sınıf oldu fakat sonuçta beklendiği gibi hata vermeden derlenip çalışıyor.
    Evet ama "hata verene kadar" doğru çalışıyor da diyebiliriz. Benim Deneme'nin kurucusu ise "exception-safe"tir.

    En azından derlemeden sonra bir sınıfın ne kadar alan gerektireceğinden eminiz o yüzden sınıfı gösteren işaretçilerin kullanılmasında sakınca olduğunu düşünmüyorum.
    İki sakınca var:

    1) Yukarıda dediğim gibi en azından fazladan bir gösterge (aslında referans_ üyesi benimkinde de perde arkasında bir göstergedir; onda bir fark yok)

    2) Üyelerin bütün erişimleri gösterge aracılığıyla yapıldığı için bütün erişimlerde yavaşlık

    3) Nesne ve onu oluşturan bu üyeler bellekte farklı yerlerde oldukları için çok çekirdekli işlemcinin ara belleğine sığmama riskleri de fazladır

    Son iki maddeyi denemedim; bir programda ölçülebilir derecede fark getirmeyebilir.

    Bütün bunların, C++ tasarımcılarının kurucu ilkleme için hoşumuza gitmeyen bir söz dizimi seçmiş olmaları yüzünden olması şanssızlık...

    Ali

  7. #17
    Ziraat Mühendisi _Onk@_ Adlı Üyenin Profil Grafiği
    Üyelik Tarihi
    09/2008
    Yer
    Ankara
    Mesaj
    713

    Alıntı acehreli, mesajından alıntı: Mesajı Gör
    1) Atanamaz nesnesinin başarıyla kurulduğunu kabul edelim. Ondan sonra KurucusuParametreAlir veya VarsayilanKurucusuPahalidir nesneleri kurulurken atılabilecek bir hata, atanamaz_'ın kaynaklarının kaybedilmelerine neden olur.
    ...
    Evet ama "hata verene kadar" doğru çalışıyor da diyebiliriz. Benim Deneme'nin kurucusu ise "exception-safe"tir.
    Evet bu oldukça önemli bir sorun. Pratikte henüz karşılaşamadım fakat teorik olarak ortaya çıkabilecek olması ihtimali dahi sinir bozucu ama madem hata atılıyor bizde yakalayabiliriz. Zaten herhangi bir hatadan sonra yapılacak en iyi şey yapılan işlemleri geri almaya çalışmaktır.

    Alıntı acehreli, mesajından alıntı: Mesajı Gör
    1) Yukarıda dediğim gibi en azından fazladan bir gösterge (aslında referans_ üyesi benimkinde de perde arkasında bir göstergedir; onda bir fark yok)

    2) Üyelerin bütün erişimleri gösterge aracılığıyla yapıldığı için bütün erişimlerde yavaşlık

    3) Nesne ve onu oluşturan bu üyeler bellekte farklı yerlerde oldukları için çok çekirdekli işlemcinin ara belleğine sığmama riskleri de fazladır

    Son iki maddeyi denemedim; bir programda ölçülebilir derecede fark getirmeyebilir.
    Sonuncu maddenin olabilirliğinden emin olmakla birlikte uygulamanın kullanıcısının da farkına varmayacağını düşünüyorum. Bellek yönetimi konusunda en basit yaklaşımı izleyen VB6 bile bu soruna neden olmadıktan sonra olabilecek en kötü şey işlemcinin toparlanmak için biraz vakit kaybetmesi olabilir.

    Alıntı acehreli, mesajından alıntı: Mesajı Gör
    Bütün bunların, C++ tasarımcılarının kurucu ilkleme için hoşumuza gitmeyen bir söz dizimi seçmiş olmaları yüzünden olması şanssızlık...
    Biz buna alışmamışlıktan ziyade cahillik diyelim. Fakat örneğinizdeki gibi bir sınıf oluşturma ihtiyacı olan bir uygulama yazacağımı düşünmüyorum.

    Peki hocam aşağıdaki kullanımda bir hata atılırsa ne olacak?

    Kod:
    class ilgincSinif
    {
    private:
    int* ip_ilginc;
    int* ip_ilginc2;
    int i_sayim;
    
    public:
    
    ilgincSinif(int i_gelecek)
    :ip_ilginc(new int),p_ilginc2(new int)
    (
    i_sayim=i_gelecek;
    ...//ip_ilginc ile ilgili işlemler
    )
    );
    

  8. #18
    Ali Çehreli
    Üyelik Tarihi
    10/2002
    Mesaj
    2,901

    O kod, Herb Sutter'ın Exceptional C++ kitabında altını çizdiği ve C++'ta yazılmaması gereken örnek (!) bir sınıftır. (Kitabın Türkçesi "Sıradışı C++")

    Bunu o kitapta "cohesion" sözcüğü ile anlatır. (Kitap şu anda yanımda olmadığı için maddesini söyleyemiyorum.) C++'da, her sınıf en fazla 1 adet kaynaktan sorumlu olmalıdır.

    ilgincSinif, ip_ilginc ve ip_ilginc2 üyelerini öyle yalın olarak değil; onlardan sorumlu akıllı göstergeler olarak tutmak zorundadır.

    Ali

  9. #19
    Ziraat Mühendisi _Onk@_ Adlı Üyenin Profil Grafiği
    Üyelik Tarihi
    09/2008
    Yer
    Ankara
    Mesaj
    713

    Bende tam Herb Bey'in makalesini okuyormuşum: http://www.gotw.ca/gotw/056.htm Hocam öneriyorsanız o kitabı edineyim.

  10. #20
    Ali Çehreli
    Üyelik Tarihi
    10/2002
    Mesaj
    2,901

    O yazar ve o kitap benim C++'ta gelişmem konusunda en etkili iki etken olmuştur!

    Ali

    Not: O kitap, C++'ı bilenlere göre yazılmıştır. Geçenlerde yeni başlayan bir arkadaş almıştı ve hayal kırıklığına uğramıştı.

+ Cevap Yaz

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Bookmarks

Mesaj Yazma Hakları

  • Yeni mesajgöndermezsiniz
  • Cevap yazamazsınız
  • Dosya ekleyemezsiniz
  • Mesajınızı düzenleyemezsiniz