Thread overview
Class'larda opEquals Overloading
Jan 10, 2022
Salih Dincer
Jan 10, 2022
Ali Çehreli
Jan 11, 2022
Salih Dincer
Jan 11, 2022
Ferhat Kurtulmuş
Jan 11, 2022
Ferhat Kurtulmuş
Jan 14, 2022
Salih Dincer
January 10, 2022

Merhaba,

Konu dağılmasın diye başka bir konuda aklıma gelen örneği buradan devam:

...mutlaka deneyeceğim. Ama önce opEquals var. Bugün sınıflardaki bir sorun için Adam'ın Pull Request'inde şöyle bir öneri var ve gayet şık gözüküyor:

import std.stdio;

/// Overrides opEquals by calling into custom method accepting typeof(this)
mixin template forwardingOpEquals()
{
    // TODO: Check that another opEquals exists
    override bool opEquals(const Object o) const
    {
        auto a = cast(typeof(this)) o;
        return a && this.opEquals(a);
    }
}

class Foo {
    int i;

    this(int i)
    {
        this.i = i;
    }

    mixin forwardingOpEquals!();

    final bool opEquals(const Foo f) const /* applicable attributes */
    {
        f.i.writeln(" == ?");
        return this.i == f.i;
    }
}


void main()
{
  int birSayı = 41;

  auto foo = new Foo(birSayı);
  auto bar = new Foo(++birSayı);
  foo.i.writeln(": ", foo == bar);
}

Gerçi şu an tartışılıyor ve belki sorun kökünden düzeltilecek sanırım.

Sevgiler, saygılar...

January 10, 2022
On 1/10/22 11:50 AM, Salih Dincer wrote:

>      override bool opEquals(const Object o) const
>      {
>          auto a = cast(typeof(this)) o;
>          return a && this.opEquals(a);
>      }

Evet, öncelikle o nesneyle aynı türden olmamız gerekiyor. Ben şu bağlantıda göstermişim:

  http://ddili.org/ders/d/object.html#ix_object.opEquals

Biraz aşağısında şöyle bir örnek var:

    override bool opEquals(Object o) const {
        const sağdaki = cast(const Saat)o;

        return (sağdaki &&
                (saat == sağdaki.saat) &&
                (dakika == sağdaki.dakika) &&
                (saniye == sağdaki.saniye));
    }

Ben typeof(this) yerine açıkça 'const Saat' yazmışım ama olsun. :) (Benim o cast'te kullandığım 'const' gereksiz.) typeof(this)'i en son düzenlediğim şu bölümde öneriyorum:

  http://ddili.org/ders/d/ozel_islevler.html

Ali


January 11, 2022

On Monday, 10 January 2022 at 20:55:08 UTC, Ali Çehreli wrote:

>

typeof(this)'i en son düzenlediğim şu bölümde öneriyorum:

http://ddili.org/ders/d/ozel_islevler.html

Hocam öncelikle üzülerek belirtmeliyim; Object başlıklı dersi ve içindeki kıymetli bilgileri es geçmişim! Belki başlığın ismi ("benim en üst sınıfla ne işim var ki" demiş olmam) etkiliydi, bilemiyorum :)

Haa bu arada typeid()'yi de yeni öğrendim ya (!) hayıflandım ve yine es geçtiğim için "pesss bana" dedim :)

Bu D, derya&deniz...

Peki bir sınıfın, içerdiği tüm elemanları ile birlikte -işlevlerden oluşan üyeleri (hatta Object'den gelen varsayılan işlevleri de) dışarıda bırakırsak- kaç byte bellekte yer işgal ettiğini öğrenebiliyor muyuz?

Biliyorum, çeşitli yöntemler var ama mesela new ile kurulduğu esnada sınıf içine aktarılan veri ve onun bağlı olduğu sınıflar ile birlikte dallanabiliyor. Yani ayrı ayrı mı hesaplamalı?

January 11, 2022

On Tuesday, 11 January 2022 at 02:54:34 UTC, Salih Dincer wrote:

>

On Monday, 10 January 2022 at 20:55:08 UTC, Ali Çehreli wrote:

>

typeof(this)'i en son düzenlediğim şu bölümde öneriyorum:

http://ddili.org/ders/d/ozel_islevler.html

Hocam öncelikle üzülerek belirtmeliyim; Object başlıklı dersi ve içindeki kıymetli bilgileri es geçmişim! Belki başlığın ismi ("benim en üst sınıfla ne işim var ki" demiş olmam) etkiliydi, bilemiyorum :)

Haa bu arada typeid()'yi de yeni öğrendim ya (!) hayıflandım ve yine es geçtiğim için "pesss bana" dedim :)

Bu D, derya&deniz...

Peki bir sınıfın, içerdiği tüm elemanları ile birlikte -işlevlerden oluşan üyeleri (hatta Object'den gelen varsayılan işlevleri de) dışarıda bırakırsak- kaç byte bellekte yer işgal ettiğini öğrenebiliyor muyuz?

Biliyorum, çeşitli yöntemler var ama mesela new ile kurulduğu esnada sınıf içine aktarılan veri ve onun bağlı olduğu sınıflar ile birlikte dallanabiliyor. Yani ayrı ayrı mı hesaplamalı?

Salih, tam olarak ne elde etmek istediğini anlamadım. Ama aşağıdaki örnek üzerinden bir şeyler anlatmak istedim. Hatalı olduğum bir yer varsa muhtemelern Ali abimiz düzeltecektir.

Sınıflar d'de referans tipleridir ve aslında arkasında (T*) gibi pointerlar çalışmaktadır. Bu yüzden örnekte A'nı elemanlarını azaltalım veya yeni elemanlar ekleyelim, her zaman aynı A.sizeof değerinini (size_t tipinden byte değeri) alırız. Struct'larda böyle değil. Ha, structlarda bir de alignment devreye girmekte, Ali abinin kitabında alignment konusuna yer verilmiş olmalı. Konumuza dönelim. A sınıfı için A.sizeof bir pointer'ın kapladığı alana karşılık geliyor. D'de sınıf instance'ının byte olarak hafızada kapladığı alanın değerini ise __traits(classInstanceSize, A) ile öğreniyoruz. İşte buradaki değer, yeni sınıf üyeleri ekledikçe veya sınıf üyelerini çıkardıkça değişir.

Gelelim class üye metodlarına. Bunları ekleyip çıkarmak classInstanceSize'ı etkilemez. Çünkü onlar sınıf tarafından aslında kapsanan fonksiyonlar değiller. Sınıf üye metodları, virtual table'da[1] o sınıfın instance'ı ile ilişkilendirilen fonksiyon pointerlarından ibaretler ve class instance boyutuna katkıları yoktur. Ancaaaaak, aşağıdaki örnekte A sınıfının bir de var4 adında bir fonksiyon pointer üyesi bulunmakta. Bunun gibi üye fonksiyon pointerları class instance boyutunu etkilerler. Çünkü o bir pointer ve bir pointerın kaplayacağı hafıza kadar yer kaplar (bende 8 byte). Sınıf üyelerini benim örneğimde yoruma alarak veya kendin yeni üyeler ekleyerek nasıl bir çıktı alıyorsun deneyip görebilirsin.

Selamlar.

1: https://dlang.org/library/object/type_info__class.vtbl.html

import std;

class B {
}

class A {
    int var1;
    ubyte var2;
    B var3;

    void function() var4;

    void f1(){}
}

void main()
{
    pragma(msg, A.sizeof);

    writeln(__traits(classInstanceSize, A));
}
January 11, 2022

On Tuesday, 11 January 2022 at 08:33:20 UTC, Ferhat Kurtulmuş wrote:

>

On Tuesday, 11 January 2022 at 02:54:34 UTC, Salih Dincer wrote:

Buradan yola çıkarak aklıma eğlenceli birşey geldi. f1 fonksiyonumuz virtual table'da 5 indeksli elemanmış. O zaman alttaki örnekte fonksiyonun adını telaffuz etmeden çalıştıralım :) (Önerilen bir kullanım değildir ;)

import std;

class B {
}

class A {
    int var1;
    ubyte var2;
    B var3;

    void function() var4;

    void f1(){
    	writeln("Naber dünya");
    }
}

void main()
{
    writeln(__traits(classInstanceSize, A));

    A a = new A();

    (cast(void function())a.classinfo.vtbl[5])();
}
January 14, 2022

On Tuesday, 11 January 2022 at 09:01:19 UTC, Ferhat Kurtulmuş wrote:

>

On Tuesday, 11 January 2022 at 08:33:20 UTC, Ferhat Kurtulmuş wrote:

>

On Tuesday, 11 January 2022 at 02:54:34 UTC, Salih Dincer wrote:

Buradan yola çıkarak aklıma eğlenceli birşey geldi. f1 fonksiyonumuz virtual table'da 5 indeksli elemanmış. O zaman alttaki örnekte fonksiyonun adını telaffuz etmeden çalıştıralım :) (Önerilen bir kullanım değildir ;)

import std;

class B {
}

class A {
    int var1;
    ubyte var2;
    B var3;

    void function() var4;

    void f1(){
    	writeln("Naber dünya");
    }
}

void main()
{
    writeln(__traits(classInstanceSize, A));

    A a = new A();

    (cast(void function())a.classinfo.vtbl[5])();
}

vtbl'ye doğrudan erişip bu örneği gösterdiğiniz için teşekkür ederim. D'yi seviyorum, insan her geçen gün yeni şeyler öğreniyor ve bitmek bilmiyor. D, adeta Derya&Deniz :)

Bu arada konu, başlıktan ayrı başka bir konuya evrildiği için (evet yine*) başka bir başlığa geçiyoruz:

Sınıf&Yapılarda Hafıza Yönetimi'ne Giriş

(*) Nedense ben bunu hep yapıyorum!