C - yapı içinde işlev


86

Bir yapının içinde bir işlev oluşturmaya çalışıyorum, şu ana kadar bu koda sahibim:

Hata : client.h: 24: 2: hata: beklenen ':', ',', ';', '}' veya ' özellik ', '{' belirtecinden önce.

Bunu yapmanın doğru yolu hangisi?


12
C'deki yapılarda işlevlere sahip olamazsınız; bunu kabaca işlev işaretçileriyle simüle etmeyi deneyebilirsiniz.
Fingolfin

1
İşlev işaretçileri kabul edilebilir bir ikame midir? stackoverflow.com/a/840703/635678
Dan O

Yanıtlar:


108

Doğrudan yapılamaz, ancak işlev işaretlerini kullanarak ve "this" parametresini açıkça ileterek aynı şeyi taklit edebilirsiniz:

Ancak, bunu yapmanın size gerçekten çok fazla şey kazandırmadığı ortaya çıktı. Bu nedenle, bu stilde uygulanan pek çok C API görmezsiniz, çünkü sadece harici işlevinizi çağırabilir ve örneği iletebilirsiniz.


3
X11 API bunun gibi bir şey yapar. XImage bakın .
Hydranix

1
Windows API altında yatan kod bununla doludur. Teknik olarak bir "pencere sınıfı", iki geri arama işlevi işaretçisi olan ve açık uçlu bir yapıdır (bu "pencere sınıfı özellikleri verileri" için kayıt olurken sağlayabilirsiniz)
Swift - Friday Pie

1
bu adımları takip etti, ancak struct.function = newFunction yaptığımda derleyici print: error: beklenen '=', ',', ';', 'asm' veya ' özellik ' önce '.' token
Bonfra

Bu, okuma işlevi ve yazma işlevi olan, ancak bir sabit sürücü türünden nexf'e değişen ortak bir hedef (ör. Sabit sürücü) istediğinizde de yararlı olacaktır
Menotdan

Gerçek uygulama çalışma zamanında seçilirse size çok şey satın alabilir. Yalnızca statik bir işleviniz varsa, her işlev çağrısında o işlev içinde her zaman yeniden seçim yapmanız gerekir, bir işlev işaretçisi kullanırsanız, seçim yalnızca bir kez gerçekleşir. Ve seçim, yapının ömrü boyunca bile değişebilir.
Mecki

24

Diğerlerinin de belirttiği gibi, işlev işaretçilerinin doğrudan yapınızın içine yerleştirilmesi genellikle geri arama işlevi gibi özel amaçlar için ayrılmıştır.

Muhtemelen istediğiniz şey daha çok sanal bir yöntem tablosu gibi bir şeydir.

Artık daha fazla işlem eklemek client_tyapının boyutunu değiştirmiyor . Şimdi, bu tür bir esneklik yalnızca birçok türde istemci tanımlamanız gerekiyorsa veya client_tarayüzünüzün kullanıcılarının işlemlerin nasıl davrandığını artırmasına izin vermek istiyorsanız yararlıdır .

Bu tür bir yapı gerçek kodda görünmektedir. OpenSSL BIO katmanı buna benzer görünür ve ayrıca UNIX aygıt sürücüsü arayüzlerinde buna benzer bir katman vardır.


15

Bu yalnızca C ++ ile çalışacaktır. Yapılardaki fonksiyonlar C'nin bir özelliği değildir.

Aynı istemciniz için de geçerlidir.AddClient (); call ... bu, nesne yönelimli programlama, yani C ++ olan bir üye işlev çağrısıdır.

Kaynağınızı bir .cpp dosyasına dönüştürün ve uygun şekilde derlediğinizden emin olun.

C'ye bağlı kalmanız gerekiyorsa, aşağıdaki kod (tür) eşdeğerdir:


1
Bu tek proje ve C'yi kullanmam gerekiyor. C'de istediğimi başarabilmemin bir yolu var mı?
xRed

Sadece bu işlevi yapının dışına taşıyın ve örneğinize bir işaretçi kabul etmesini sağlayın.
user123

Client.AddClient () şeyi biraz karmaşık sihir olmadan mümkün olmayacak (diğer cevaba bakınız).
QSQ

14

Buna ne dersin?


"Biraz" JavaScrip benzeri bir çözüm
Bitman

8

Kodu yapıya göre gruplandırmaya çalışıyorsunuz. C gruplaması dosyalardır. Tüm işlevleri ve dahili değişkenleri bir başlığa veya başlığa ve ac kaynak dosyasından derlenen bir nesne ".o" dosyasına koyarsınız.

Nesne yönelimli bir dil olmayan bir C programı için nesne yönelimini sıfırdan yeniden icat etmek gerekli değildir.

Ben bunu daha önce görmüştüm. Tuhaf bir şey. Bazıları kodlayıcılar, değiştirmek istedikleri bir nesneyi değiştirmek için bir işleve geçirmekten kaçınırlar, bunu yapmanın standart yolu bu olsa bile.

C ++ 'ı suçluyorum, çünkü sınıf nesnesinin bir üye işlevinde her zaman ilk parametre olduğu, ancak gizli olduğu gerçeğini gizledi. Dolayısıyla, öyle olsa bile, nesneyi işleve geçirmiyor gibi görünüyor.

C esnektir ve referans olarak geçen şeyleri alabilir.

AC işlevi genellikle yalnızca bir durum baytı veya int döndürür ve bu genellikle göz ardı edilir. Sizin durumunuzda uygun bir form olabilir

addClient, Client.h veya Client.c içinde olacaktır.


Yaklaşımın artıları ve eksileri var. Sırf her zaman yapıldığı gibi , hem OO olmayan ( do(object, subject)) hem de OO ( subject.do(object)) fonksiyonları düzenleme stratejilerine atıfta bulunmak, denemeyi bırakmamız gerektiği anlamına gelmez. Bunun C'nin yazıldığı tarihsel yol olmadığını ve C'nin bu şekilde yazılmasına gerek olmadığını belirtmenin geçerli olduğunu düşünüyorum (aynısı birçok dil için de geçerlidir, özellikle prosedürel, işlevsel veya mantık paradigmalarından gelir), ama bu kalıbı aktif olarak caydırmamıza gerek yok. Bazı faydaları da var
hiljusti

0

Struct işaretçisini işlev bağımsız değişkeni olarak işlev görecek şekilde iletebilirsiniz. Referansla geçiş denir.

Bu işaretçinin içindeki bir şeyi değiştirirseniz, diğerleri olarak güncellenecektir. Şöyle dene:


Referans ile geçiş yoktur C'dir. İmlecin bir kopyasını geçiriyorsunuz, işaretçinin referansları aynı, ancak işaretçilerin kendisi hayır.
Çavuş Cortez

Düzeltme için teşekkürler. Tutorialspoint'ten C pass by reference tutorial'ı okudum . Bu yukarıda yazdığımdan farklı mı?
Hadi Hidayet Hammurabi
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.