Bir C yapısı bir işlevi varmış gibi davranabilir mi?


13

structBir yapının üyelere sahip olabileceği ancak fonksiyonların bulunmadığı yerlerde C ve s kullanıyorum . Basitlik için ben ad dizeleri için bir yapı oluşturmak istediğinizi varsayalım ve dize dizini ve pozisyonda karakteri değiştirmek için karakter nerede stryapmak istiyorum varsayalım . Yapılar işlevlere sahip olamayacağı için bu asla mümkün olmaz mı veya hala bu davranışı uygulayabileceğimiz ve bir yapının aslında sadece yeni bir yapıya kendisini kopyalayan ve kendisini güncelleyen yapının (basit) bir işlevi olabileceğini taklit edebileceğimiz bir yol var mı? hangi alanlarda yapabilirdi?str.replace(int i, char c)ici

Böylece replace, yapının erişildiği veya benzer olduğu zaman güncellenen yeni bir yapıya işaret eden üçüncü bir yapı üyesi olabilir. Bu yapılabilir mi? Ya da niyetimi engelleyen yerleşik bir şey ya da bir teori ya da paradigma var mı?

Arka plan C kodu yazıyorum ve kendimi biliyorum ki OOP dillerinde kütüphane yerleşik olduğunu ve OOP dizeleri ve komutları işlemek için iyi bir yol olacağını biliyorum fonksiyonları yeniden icat bulmak.


5
Dürüst olmak gerekirse, bu tür şeyleri yapmak için ücretsiz işlevler yazmanın daha iyi olacağını düşünüyorum. Ancak, gerekli moxie'niz
Robert Harvey'i

5
Yapılar, işlevlere işaret eden değişkenler içerebilir. Yerleşik kalıtım yok, ancak aynı imzayla farklı işlevlere işaret eden işaretçilerle yapınızı başlatabilirsiniz. Genellikle işlevin ilk parametresini yapıya bir işaretçi yapmak istersiniz.
James McLeod

29
replace (& str, i, c) gerçekten str.replace (i, c) 'den çok daha mı kötü? Sorunuz aslında işlevleri değiştirmekle ilgili değil, C'ye yeni bir sözdizimi atmaya çalışmakla ilgili.
whatsisname

1
@RobertHarvey cs.rit.edu/~ats/books/ooc.pdf bağlantısı için teşekkürler . Güzel bir kitap (ve fiyat doğru).
John Forkosh

3
@ whatsisname: C'de, yapı işaretçisini zaten işleve geçirmeniz gerekir, böylece str.replace(&str, i, c)yine de sonuçlanırsınız . C ++ this, elbette işaretçinin geçişini otomatikleştirir .
Jonathan Leffler

Yanıtlar:


21

İşlevin böyle görünmeli.

void
replace(struct string * s, int i, char c);

Bu, ilk parametre olarak üzerinde çalışılacak nesneye bir işaretçi kabul eder. C ++ 'da, bu this-pointer olarak bilinir ve açıkça bildirilmesi gerekmez. (Bunu, bulunduğu Python ile karşılaştırın.)

İşlevinizi çağırmak için, bu işaretçiyi de açıkça geçirirsiniz. Temel olarak, o.f(…)söz diziminin sözdizimi ile ticaretini yaparsınız f(&o, …). Önemli bir şey değil.

Eğer polimorfizmi (diğer bir deyişle virtualfonksiyonlar) desteklemek istiyorsanız hikaye daha karmaşık hale gelir . Ayrıca C de taklit edilebilir ( bu cevap için gösterdim .) Ama elle yapmak güzel değil.

As Jan Hudec yorumladı, ayrıca bu tip adıyla (yani birlikte işlev adı öneki bir alışkanlık yapmalıdır string_replaceC hiçbir ad-boşluk olduğundan sadece adında tek işlevi olabilir böylece) replace.


17
Tabii ki fonksiyon muhtemelen çağrılmak zorunda kalacak string_replace, çünkü C'nin fonksiyon aşırı yüklenmesi de yok ve muhtemelen replacebaşka bir tip için başka bir
şeye

2
İsimlendirilemez string_replace. İle başlayan isimler str, memya wcsbir küçük harflerden oluşan gelecekteki uzantıları için ayrılmıştır.
David Conrad

43

Yapılar işlev işaretçileri tutabilir , ancak bunlar yalnızca sanal yöntemler için gereklidir. Nesne yönelimli C'deki sanal olmayan yöntemler genellikle yapıyı ilk argüman olarak normal bir işleve geçirerek yapılır. C için bir OOP çerçevesinin iyi bir örneğini görmek için Gobject'e bakın. Miras ve polimorfizm için gerekli olan çok sayıda kazan plakasını işlemek için makrolar kullanır.

C 44 yıl önce kuruldu. Açık kaynak için çok popüler bir dildir. Standart C dizelerinin üzerinde çalışmanın zor olduğunu düşünen ilk kişi siz değilsiniz. C string kitaplıkları için bazı aramalar yapın. Tekerleği yeniden icat etmek zorunda değilsiniz.


2
Dikkate değer diğer bir örnek ise CPython'dur. Kod çok sayıda OOP kavramı kullanıyor, ancak% 100 saf C
Bakuriu

@Bakuriu Ne karıştırıyorsun düşünüyorum Cython ve CPython
kedi

1
@cat Muhtemelen Python C API'sini ifade eder, Cython% 100 saf C. değildir. docs.python.org/c-api/intro.html
JAB

5
@cat Hayır. CPython kaynaklarına bakın. Çoğu şey gerçekten OOP paradigması kullanılarak yapılır ve çoğunlukla python API ile eşleşen bir OOP API'si sağlarlar.
Bakuriu

1
@Bakuriu Oh, Python'un dilini değil Python'un çalışma zamanını, kaynağını ve C API'sini kastediyorsunuz.
kedi

8

İşlev işaretçileriyle şunları yapabilirsiniz:

str.replace(&str, i, c);

Bu genellikle yalnızca uygulama değişebiliyorsa yararlıdır; bu durumda, bir vtable kullanmalısınız, böylece ek yük yapı başına yalnızca bir işaretçi olur:

str.vtable->replace(&str, i, c);

3
Hala string_replace (& str, i, c) olarak çağırmak eğilimindedir sonra çağrı sitesi vtable hakkında bilmek yerine string_replace içinde vtable kullanın.
Pete Kirkham

2
@Pete str(veya memveya wcs) ile başlayan isimler ve küçük harf C standardı tarafından gelecekteki uzatmalar için ayrılmıştır, bu yüzden çağırma string_replace. str_replaceiyi.
David Conrad

3

Evet, yapabilirler. C'nin işaretçilerin hafızadaki fonksiyon bloklarına, yani fonksiyon işaretleyicilerine izin vermesini ve bunu kullanarak çok işlevli olmasa bile çok işlevli polimorfizm gibi bir arayüz oluşturabileceğiniz gerçeğinden faydalanabilirsiniz.

Bu konuyla ilgili bir blog yazısı yazdım, öğrencilerimden birinden, C ve Go'daki arayüz benzeri kodla ilgili bir soruyu takiben, buradan okuyabilirsiniz:

OO olmayan arayüzlerde blog yazısı

Size herhangi bir fikir verip vermediğine bakın.

Ayrıca, kodunuza ücretsiz bir işlev koyabilir ve "bu" işaretçi kullanabilirsiniz, yani diğer yanıtlarda açıklandığı gibi üzerinde çalışmak için mevcut bir yapıya bir işaretçi geçirirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.