Ne zaman bir sınıf vs bir yapı C ++ kullanmalısınız?


949

Hangi senaryolarda C ++ ' da structvs a kullanmak daha iyidir class?


47
Bu sadece C ++ için değil, hem yapıları hem de sınıfları sağlayan herhangi bir dile uygulanabilir.
Jason Bunting

3
Hala katılmıyorum - bu soruya anlamsal olarak yaklaşıyorum. Belki bazı teknik farklılıklar vardır, ancak anlamsal olarak değildirler. Yapılar gerçekten değer türleri oluşturmak için yararlıdır, sınıflar değildir.
Jason Bunting

4
C ++ 'da yapı kullanmak için ciddi bir neden olmadığına inanıyorum. Bana göre yapılar sadece C ile uyumluluk için var olan C ++ 'ın typedefs gibi bir başka "özelliği" dir. C ++ başlangıçta C'nin bir uzantısı olarak ele alınmadıysa ve Java gibi sıfırdan tasarlanmışsa bunlar olmazdı. Genel olarak, C ++ ile ilgili en garip şeylerin C uyumluluğu ile ilgisi olduğunu düşünüyorum.
Kostas

5
Yapı - POD (düz eski veriler) ve tüm üye erişilebilirlikleri herkese açıktır. Sınıf - Daha iyi bir kapsüllemeye ihtiyacınız olduğunda ve sınıfın durumuyla çalışmak için üye işlevlerine ihtiyacınız olduğunda.
Navaneeth KN

4
Bu sadece sözleşmeyle geçerlidir. Varsayılan kapsülleme dışında bir fark yoktur.
Dave Hillier

Yanıtlar:


804

C ++ 'da a classve a structarasındaki farklar , yapıların varsayılan publicüyelere ve tabanlara ve sınıfların varsayılan privateüyelere ve tabanlara sahip olmasıdır. Her iki sınıf ve yapılar bir karışımına sahip olabilir public, protectedve privateüyeleri miras kullanabilir ve üye işlevlerini sahip olabilir.

Herhangi bir sınıf benzeri özelliği olmayan yapıları düz-eski-veri yapıları olarak kullanmanızı ve privateveri ve üye fonksiyonları ile toplu veri yapıları olarak sınıfları kullanmanızı tavsiye ederim .


99
Değiştirici veya yöntem içermeyen bir yapıya, C kütüphaneleriyle geriye dönük olarak uyumlu bir arayüz olarak var olan (sözde) bir C yapısı gibi düzenlenmiş olduğu garanti edilen bir POD yapısı denir. Bununla birlikte, bu tek istisna dışında, tek fark belirtildiği gibidir.
workmad3

26
@ workmad3: Ad yanıltıcı, ancak 9/4 (C ++ 03) diyor ki: "POD-yapısı, POD-yapı olmayan, POD-birliği olmayan tipte statik olmayan veri üyelerine sahip olmayan bir toplu sınıftır (veya bu tür bir dizi) veya başvuruyu içermez ve kullanıcı tanımlı bir kopya atama operatörü ve kullanıcı tanımlı yıkıcı içermez. " "Struct" sınıf anahtarını kullanma konusunda herhangi bir kısıtlama ve "public" kullanımında herhangi bir kısıtlama yoktur (toplam gereksinimler için bkz. 8.5.1 / 1). Bu "yapı" ve "sınıf" arasında bir fark değildir.

5
"Agrega" kullanımınız, standardın tanımı göz önüne alındığında yanlış anlaşılabilir. :)

3
Stroustrup'un "İlkeler ve Uygulama" kitabına göre: "Yapılar öncelikle üyelerin herhangi bir değer alabileceği yerlerde kullanılmalıdır" (yani anlamlı bir sınıf değişmezinin tanımlanamayacağı yerlerde)
antibus

6
Elbette C ile arayüz oluştururken sınıfları kullanabilirsiniz. Sınıflar ve yapılar arasında fark yoktur. Yapılar sınıflardır; yalnızca varsayılan erişim özelden genel kullanıma çevrilir.
Sebastian Mach

229

Herkesin belirttiği gibi, gerçekten sadece iki gerçek dil farkı vardır:

  • structvarsayılan olarak genel erişime ve classvarsayılan olarak özel erişime sahiptir.
  • Devralınırken , structvarsayılan olarak publicdevralma ve classvarsayılan olarak privatedevralma. (İronik olarak, C ++ 'da pek çok şeyde olduğu gibi, varsayılan değer geriye doğrudur: publickalıtım çok daha yaygın bir seçimdir, ancak insanlar nadiren struct" public" anahtar kelimesini yazarken kaydetmek için nadiren bildirir .

Ancak uygulamadaki gerçek fark , bir kurucu / yıkıcı ilan eden ve olmayan bir class/ arasındadır struct. "Düz-eski-veri" POD tipi için, sınıfın yapısını ele geçirdikten sonra artık geçerli olmayan belirli garantiler vardır. Bu ayrımı açık tutmak için, birçok kişi kasıtlı olarak sadece structPOD türleri için s kullanır ve eğer herhangi bir yöntem ekleyeceklerse classes'yi kullanır . Aşağıdaki iki parça arasındaki fark aksi anlamsızdır:

class X
{
  public:

  // ...
};

struct X
{
  // ...
};

(Bu arada, "POD tipi" nin aslında ne anlama geldiği hakkında bazı iyi açıklamaları olan bir iş parçacığı: C ++ 'da POD türleri nedir? )


Kalıtım farklılıklarına ilişkin güzel bir örnek: burada .
Liran Orevi

8
Kullanmak İster structya classda nesne POD olup olmadığı ile bir ilgisi yoktur veya bir kopya yapıcı / yıkıcı tanımlamak gerekip gerekmediğini. Üye işlevlerinin de POD olan bir şey üzerinde hiçbir etkisi yoktur. Yazdıklarınızı tekrar okuduğumda, başka türlü
David Stone

1
@DavidStone Temel olarak, POD yapılarının C koduyla geriye dönük olarak uyumlu olmaları ve bu nedenle temelde C-tarzı yapılar olarak tasarlanmaları beklenir.
Justin Time - Monica'yı

3
Bu cevabın "gerçek farkı" kısmı tamamen yanlış.
juanchopanza

177

Mevcut cevaplarda birçok yanlış anlama var.

Her ikisi de classve structbir sınıf ilan.

Evet, sınıfı bildirmek için kullandığınız anahtar kelimeye bağlı olarak, erişim değiştiren anahtar kelimelerinizi sınıf tanımı içinde yeniden düzenlemeniz gerekebilir.

Ancak, sözdiziminin ötesinde, birini diğerinden seçmenin tek nedeni kongre / stil / tercihtir.

Bazı insanlar structüye işlevleri olmayan sınıflar için anahtar kelimeye bağlı kalmayı severler , çünkü elde edilen tanım C'den basit bir yapıya "benziyor".

Benzer şekilde, bazı insanlar classanahtar kelimeyi üye işlevleri ve privateverileri olan sınıflar için kullanmayı sever , çünkü üzerinde "sınıf" yazar ve bu nedenle nesne yönelimli programlama hakkındaki en sevdikleri kitaptan örneklere benzer.

Gerçek şu ki, bu tamamen size ve ekibinize bağlıdır ve programınız için tam anlamıyla bir fark yaratmayacaktır.

Aşağıdaki iki sınıf, adları dışında her şekilde kesinlikle eşdeğerdir:

struct Foo
{
   int x;
};

class Bar
{
public:
   int x;
};

Tekrar bildirirken anahtar kelimeleri de değiştirebilirsiniz:

class Foo;
struct Bar;

( bu, Visual Studio'nun uyumsuzluk nedeniyle oluşmasına rağmen , derleyici bunu yaptığınızda bir uyarı verecektir.)

ve aşağıdaki ifadelerin her ikisi de doğru olarak değerlendirilir:

std::is_class<Foo>::value
std::is_class<Bar>::value

Anahtar kelimeleri geçemezsiniz, ancak, not Do yeniden tanımlanması ; bunun nedeni, (tek tanım kuralı uyarınca) çeviri birimleri arasındaki çift sınıf tanımlarının "aynı token dizisinden oluşması" gerektiğidir . Bu araçlar bile alışverişi olamaz const int member;ile int const member;ve semantik ile ilgisi yoktur classya struct.


15
Bu çok bilgilendirici ve dürüstçe en sevdiğim cevaptı. Diğer herkes onlara ayrı varlıklar olarak davranıyor, kaputun altındayken aynılar. Arduino ortamındaki bir yapı tanımının c ++ sınıfı olarak kabul edilip edilmediğini merak ediyorum.
Benjamin

4
@Ben Tabii ki öyle. Arduino derleyicisi C ++ derler; bunun sonu.
underscore_d

6
Bu hakkı anlıyorsam: Görünürlük değiştiricileriniz açık olduğu sürece, atlanmadığı sürece önemli değil. Yapılar dışında hiçbir şey kullanarak büyük bir C ++ uygulaması yazabilirsiniz; ya da her yapı örneğini sınıf olarak değiştirebilirsin. Varsayılan görünürlüğü kullanmadığınız sürece, uygulamalar tam olarak aynı olacaktır.
Ryan Lundy

Bir C ++ programının bir çeviri biriminin tam beyanı class foo { public: ... };ve diğerinin struct foo { ... };"kesinlikle eşdeğer" iddiasına göre doğru olması gerekebileceğine ikna olmadım . Eksik beyanların struct foo;ve class foo;birbirinin yerine geçebileceği mantığına gelir . Bunlar sınıf gövdesini belirtmez ve bu nedenle erişim düzenine hiçbir şey söylemezler.
Kaz

@Kaz: Haklısın - eğer tanımlar kelimenin tam anlamıyla aynı tipteyse, davranışın iyi tanımlanması için sözlüksel olarak aynı olmaları gerekir. Yapı anahtar ve sınıf anahtar aksi mantıksal (semantik etkilenmez) değiştirilebilir olsa, ve Foove Baryine / aynı tip eşdeğerdir. " Yeniden yazarken " derken bir örnek verdim . Bunu düşünmeye gel, insanları UB'ye yönlendirmemeyi sağlamak için cevabı açıklığa kavuşturacağım
Orbit'teki Lightness Races

54

Bir sınıf yerine bir yapı kullandığım tek zaman, bir işlev çağrısında kullanmadan hemen önce bir functor bildirmek ve netlik uğruna sözdizimini en aza indirmek istiyorum. Örneğin:

struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare()); 

35
Birkaç yıl sonra ve C ++ 11 tüm büyük derleyiciler tarafından desteklendiğine göre, Lambdas bunu daha da özlü hale getiriyor .

36

Gönderen C ++ SSS Lite :

Bir yapının üyeleri ve temel sınıfları varsayılan olarak herkese açıktır, sınıfta ise varsayılan olarak özeldir. Not: Temel sınıflarınızı varsayılanlara güvenmek yerine açıkça herkese açık, gizli veya korumalı hale getirmelisiniz.

yapı ve sınıf, işlevsel olarak eşdeğerdir.

Tamam, o gıcırtılı temiz tekno konuşmasından yeterince. Duygusal olarak, çoğu geliştirici sınıf ve yapı arasında güçlü bir ayrım yapar. Bir yapı, kapsülleme veya işlevsellik yolunda çok az olan açık bir bit yığını gibi hisseder. Bir sınıf, akıllı hizmetler, güçlü bir kapsülleme engeli ve iyi tanımlanmış bir arayüzle toplumun yaşayan ve sorumlu bir üyesi gibi hissediyor. Çoğu insanın zaten sahip olduğu çağrışım olduğundan, çok az yöntemi olan ve genel verilere sahip bir sınıfınız varsa (böyle şeyler iyi tasarlanmış sistemlerde var!) Büyük olasılıkla struct anahtar sözcüğünü kullanmalısınız, aksi takdirde sınıfı kullanmalısınız anahtar kelime.


1
Neden yapının ve sınıfın işlevsel olarak aynı olduğunu belirttiler, ama herhangi bir gerekçe olmaksızın belirli durumlarda diğerini tercih ettiğini söyleyerek
anlamıyorum

3
Nedeni konvansiyon. Derleyici hangisini kullandığınızla ilgilenmez, ancak kodunuza bakan başka bir geliştirici ne demek istediğinizi anlamak için daha kolay bir zamana sahip olacaktır.
Tal Pressman

3
@ deetz: Üçüncü paragrafın tamamı mantıklı.
Orbit'te Hafiflik Yarışları

Vay canına, 'eski okuldan' gelen bir yapının yöntemlere ve hatta mirasa sahip olabileceği hakkında hiçbir fikrim yoktu. Ben sadece hiçbir yöntem ile sadece veri kullanırken her zaman yapıyı kullandım ve genellikle yapı gerektiren API kodu ile uğraşırken. Yapılar birden fazla mirası da destekleyebilir mi?
Paul McCarthy

21

Bir yapının benim için yararlı olduğu bir yer, başka bir sistemden sabit formatlı mesajlar (örneğin bir seri port) alan bir sistemim olduğunda. Bayt akışını alanlarınızı tanımlayan bir yapıya atabilir ve ardından alanlara kolayca erişebilirsiniz.

typedef struct
{
    int messageId;
    int messageCounter;
    int messageData;
} tMessageType;

void processMessage(unsigned char *rawMessage)
{
    tMessageType *messageFields = (tMessageType *)rawMessage;
    printf("MessageId is %d\n", messageFields->messageId);
}

Açıkçası, bu C ile aynı şeydir, ancak mesajı bir sınıfa deşifre etmenin yükünün genellikle buna değmediğini görüyorum.


Aynı şey
C.'de

11
Ya da sadece uygulamak operator >>yerine yazılı bir sınıfına processMessageda C yapacağı işlevi, ++ daha uygun C ++ gibi ve daha az C gibi görünüm
Nick Bastin

1
Farklı sistemler arasında taşınabilir olmadığı gerçeğinin yanı sıra, diğer adlandırma kurallarını da ihlal ettiğinden, tek bir mimari içinde bile çalışacağı garanti edilmez.
underscore_d

@underscore_d Bu, platformdan bağımsız olarak çalışabilir (derleyici değil), ancak sabit bit alanlarını, bir __packed__yapıyı kullanmanız ve endian farkında bir ifdef uygulamasına sahip olmanız gerekir (endianess'in dış veri kaynağının ters olduğu bir makinede siparişi çevirmeniz gerekir Sağlıyor). Bu hoş değil, ancak gömülü platformlardaki uzak çevre birimleri için kayıtları taşınabilir bir şekilde paketledim / paketinden çıkarttım.
crasic

1
@jacwah Huh, iyi bir nokta. Takma charad burada bir sorun olmayacak çünkü işaretçilerden biri takma isimden muaf bir tür. Bununla birlikte, yine de farklı bir sorun olsa da: char*Farklı bir türe a dökülmesi , eğer o adreste zaten başlatılmış olan ikinci tipte herhangi bir nesne yoksa, yaşam boyu kurallarını ihlal ettiği için UB'dir. Afaik, hedef türü önemsiz bir şekilde yapılandırılabilir olsa bile, sadece ayrılmış bellek olması C ++ için bu belleğin bu tür olarak resmen işlenmesine izin vermek için yeterli değildir.
underscore_d

19

Dahili C ++ olan bir kitaplık yazıyorsanız ancak API C veya C ++ koduyla çağrılabilirse, C ++ 'da "struct" kullanabilirsiniz. Sadece hem C hem de C ++ koduna maruz bıraktığınız yapıları ve global API işlevlerini içeren tek bir üstbilgi yaparsınız:

// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif

// Put your C struct's here
struct foo
{
    ...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;

// Put your C API functions here
void bar(foo *fun);

#ifdef __cpp
}
#endif

Daha sonra C ++ kodunu kullanarak bir C ++ dosyasına bir işlev çubuğu () yazabilir ve C'den çağrılabilir yapabilirsiniz ve iki dünya, bildirilen yapı üzerinden veri paylaşabilir. C ve C ++ 'ı karıştırırken elbette başka uyarılar da var, ancak bu basitleştirilmiş bir örnektir.


2
En uygun cevap. C-uyumluluğu gerçekten en önemli nedendir. varsayılan erişim gibi diğer tüm şeyler ezoteriktir.
Valentin Heinitz

16

Her birinin söylediği gibi, tek gerçek fark varsayılan erişimdir. Ancak, bazı yardımcı yöntemleri uygulasam bile, basit bir veri sınıfıyla herhangi bir kapsülleme istemediğimde özellikle yapı kullanıyorum. Örneğin, böyle bir şeye ihtiyacım olduğunda:

struct myvec {
    int x;
    int y;
    int z;

    int length() {return x+y+z;}
};

1
+1, "yapıyı elinizden aldığınız" gibi hissetmeyen bazı üye işlevlere sahip bir yapı örneği vermek için.
einpoklum

9

Kendi sorumu (utanmadan) cevaplamak için, Daha önce de belirtildiği gibi, erişim ayrıcalıkları C ++ 'da tek farktır.

Bir yapıyı yalnızca veri depolama için kullanma eğilimindeyim. Verilerle çalışmayı kolaylaştırırsa birkaç yardımcı işlev almasına izin vereceğim. Ancak, veri akış kontrolü gerektirdiğinde (yani dahili bir durumu koruyan veya koruyan alıcılar / ayarlayıcılar) veya herhangi bir büyük işlevselliği (temelde daha fazla nesne benzeri) elde etmeye başlar başlamaz, daha iyi iletişim kurmak için bir sınıfa 'yükseltilir'.


9

Yapılar ( POD'lar) , daha genel olarak), C ++ uygulamasıyla C uyumlu bir arayüz sağlarken kullanışlıdır, çünkü bunlar dil sınırları ve bağlayıcı formatları arasında taşınabilir.

Bu sizin için bir endişe değilse, o zaman "sınıf" yerine "yapı" kullanımı niyet iyi bir iletişim olduğunu varsayalım (@ZeroSignal yukarıda söylediğim gibi). Yapılar ayrıca daha öngörülebilir kopyalama semantiğine sahiptir, bu nedenle harici ortama yazmayı veya kablo üzerinden göndermeyi düşündüğünüz veriler için yararlıdır.

Yapılar, sadece bir grup bağımlı typedef'i ortaya çıkaran özellik şablonları gibi çeşitli meta programlama görevleri için de kullanışlıdır:

template <typename T> struct type_traits {
  typedef T type;
  typedef T::iterator_type iterator_type;
  ...
};

... Ama bu sadece yapının varsayılan koruma düzeyinin halka açık olmasından faydalanıyor ...


1
Bu, POD'un doğru kullanımı değildir. Bir yapı (veya sınıf) SADECE POD üyeleri içeriyorsa (ve yalnızca) POD yapısı olabilir.
Martin York

4
"öngörülebilir kopyalama semantiği": Symantics, sınıfla aynıdır (ve aynı sorunlara sahiptir (sığ kopya)).
Martin York

2
Bu yazı (umarım kazara) tüm yapıların POD olduğuna inanırsınız. Bu hiç de doğru değil. Umarım insanlar bu konuda yanıltıcı değildir.
Michael Dorst

8

C ++ için, yapılar ve sınıflar arasında pek bir fark yoktur. Temel fonksiyonel fark, yapıların üyelerinin varsayılan olarak herkese açık olmaları ve sınıflarda varsayılan olarak gizli olmalarıdır. Aksi takdirde, dil söz konusu olduğunda, bunlar eşdeğerdir.

Bununla birlikte, Brian'ın söylediklerine benzer şekilde, C # 'da yaptığım gibi C ++' daki yapıları kullanma eğilimindeyim dedi. Yapılar basit veri kaplarıyken, sınıflar yalnızca veri üzerinde tutmanın yanı sıra veriler üzerinde hareket etmesi gereken nesneler için de kullanılır.


4

Onlar hemen hemen aynı şey. C ++ büyüsü sayesinde, bir yapı işlevleri tutabilir, kalıtım kullanabilir, "new" kullanarak yaratılabilir ve tıpkı bir sınıf gibi

Tek işlevsel fark, bir sınıfın özel erişim haklarıyla başlarken, bir yapı halkla başlar. Bu, C ile geriye doğru uyumluluğu korumaktır.

Uygulamada, yapıları her zaman veri sahipleri olarak ve sınıfları nesne olarak kullandım.


4

Diğerlerinin işaret ettiği gibi

  • her ikisi de varsayılan görünürlük dışında eşdeğerdir
  • herhangi bir sebepten ötürü birini veya diğerini kullanmaya zorlanmak için nedenler olabilir

Stroustrup / Sutter'dan ne zaman kullanılacağı hakkında net bir öneri var:

Sınıfın bir değişmezi varsa sınıfı kullanın; veri üyeleri bağımsız olarak değişebiliyorsa struct kullan

Ancak, beyanı iletmenin akıllıca olmadığını unutmayın. class ( class X;) olarak tanımlayın ve struct ( struct X { ... }) olarak tanımlayın . Bazı bağlayıcılarda (örn. G ++) çalışabilir ve diğerlerinde başarısız olabilir (örn. MSVC), böylece kendinizi geliştirici cehenneminde bulacaksınız.


Bu linker sorunlarını tarif edebilir misiniz?
Orbit'te Hafiflik Yarışları

@LightnessRacesinOrbit Ne yazık ki yapamam. Bir örnek bile yapamıyorum. Önemsiz class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }şey sadece MSVC 2017'yi derlemek ve çalıştırmakla kalmaz, aynı zamanda Fooolarak structtanımlanan ancak olarak tanımlanmış net bir uyarı üretir class. Ama aynı zamanda bu aptal hatayı bulmak için ekibimizin yarım güne mal olduğunu açıkça hatırlıyorum. O zamanlar hangi MSVC sürümünü kullandığımızdan emin değilim.
pasbi

Bağlayıcı, kullandığınız veya ileri bir beyanda bulunup bulunmadığınızı bile bilmemeli ve ikisi standart başına serbestçe değiştirilebilir (VS'nin uyardığı biliniyor; Her zaman bunun sadece belirgin programcı hatalarından kaçınmak olduğunu varsaydım). Burada bir şey kokmuyor. Bir ODR ihlali hatası olmadığından emin misiniz? classstruct
Yörüngedeki Hafiflik Yarışları


Tam olarak hatırlamıyorum. Sorun doğrudan bir uygulamada değil, bir testte kullanılan bir kütüphanede oluştu. Sadece linker anlaşılmaz hatalar ürettiğini biliyorum (LNK ???). Ben struct-forward'dan -forward'a classgeçince problemler ortadan kayboldu. Bugün itibariyle onu da garip buluyorum. Üzerine biraz ışık tutabilirseniz sevinirim.
pasbi

3

Sınıf.

Sınıf üyeleri varsayılan olarak gizlidir.

class test_one {
    int main_one();
};

Eşittir

class test_one {
  private:
    int main_one();
};

Yani denersen

int two = one.main_one();

Bir hata alırız: main_one is privateçünkü erişilebilir değil. Herkese açık olarak belirterek başlatarak çözebiliriz.

class test_one {
  public:
    int main_one();
};

Struct.

Yapı, üyelerin varsayılan olarak herkese açık olduğu bir sınıftır.

struct test_one {
    int main_one;
};

main_oneÖzel araçlar yani

class test_one {
  public:
    int main_one;
};

Üyelerin herhangi bir değer alabileceği veri yapıları için yapıları kullanıyorum, bu şekilde daha kolay.


3

Bir avantajı structüzerinde class"o zaman özel, ilk kamu üyelerine" bağlı kalarak eğer, bir satır kodun kurtarmak olmasıdır. Bu ışık altında, anahtar kelimeyi classişe yaramaz buluyorum.

Burada sadece kullanmak için bir başka nedendir structve asla class. C ++ için bazı kod stili yönergeleri, işlev makroları için küçük harfler kullanılmasını önerir; bunun mantığı, makro bir satır içi işleve dönüştürüldüğünde adın değiştirilmesi gerekmemesidir. Burada aynı. Güzel C tarzı yapınız var ve bir gün, bir yapıcı veya bir kolaylık yöntemi eklemeniz gerektiğini öğreniyorsunuz. Bunu birclass ? Her yerde?

Arasındaki ayrım structS ve classes çok zor bir iştir, ne yapmamız gerektiğini - programlamayı - yapmaktır. C ++ 'ın birçok problemi gibi, geriye dönük uyumluluk konusundaki güçlü arzudan kaynaklanmaktadır.


Neden bunu bir olarak değiştirmeniz gerekiyor class? structAnahtar kelimeyle tanımlanan bir sınıfın üye işlevlerine veya bir kurucuya sahip olamayacağını mı düşündünüz ?
Yörüngedeki Hafiflik Yarışları

@LightnessRacesinOrbit nedeniyle 1. tutarlılık ve 2. bazı statik analizörleri 1 ihlali şikayet.
Vorac

Bunu takip etmiyor. Başka hangi "tutarlılıklara" bağlı kalıyorsunuz? Adlı bir üyesi olan her sınıf anahtar kelime joe()ile tanımlanmalıdır class? En az 4 intüyesi olan her sınıf structanahtar kelime ile mi tanımlanmalıdır ?
Yörüngedeki Hafiflik Yarışları

@LightnessRacesinOrbit Ben deyimden bahsediyorum "POD agregaları ile tanımlanır struct , yöntemlerleclass . Çok fazla güçlük.
Vorac

2

farklı varsayılanlarla aynı şeydir (varsayılan olarak özel ve varsayılan olarak classherkese açık struct), bu nedenle teoride tamamen değiştirilebilirler.

yani, sadece hareket etmek için bazı bilgileri paketlemek istiyorsanız, ben orada birkaç yöntem koymak (ama çok değil) bile, bir yapı kullanın. Temel kullanımın doğrudan veri üyelerine değil, yöntemlerle olacağı çoğunlukla opak bir şeyse, tam bir sınıf kullanırım.


2

Yapılar varsayılan olarak genel erişime ve sınıflar varsayılan olarak özel erişime sahiptir.

Şahsen Veri Aktarım Nesneleri veya Değer Nesneleri olarak yapıları kullanıyorum. Bu şekilde kullanıldığında, tüm üyeleri diğer kodlarla değiştirilmesini önlemek için const olarak beyan ederim.


2

Hem structve classgerçi görünürlüğe gibi farklı varsayılanlarla başlık altında aynıdır, structvarsayılan kamu ve classvarsayılan özeldir. Sen uygun kullanımı ile diğer olmak ikisinden birini değiştirebilir privatevepublic . Her ikisi de mirasa, yöntemlere, kuruculara, yıkıcılara ve nesne yönelimli bir dilin tüm güzelliklerine izin verir.

Ancak ikisi arasındaki büyük fark, structanahtar kelime C olarak desteklenirken desteklenmemesidir class. Tek bir kullanabileceği Bu araçlar structbir olabilir dosyası içerir #includesürece ya C ++ veya C içine structdüz bir C tarzı structve diğer her şeyin dosyası yani hiçbir C ++ gibi spesifik anahtar kelimeler, C uyumlu dahil private, publichiçbir yöntemleri, kalıtım yok vb.

AC stili struct, structverileri arayüz üzerinde ileri ve geri taşımak için C stilinin kullanılmasını destekleyen diğer arabirimlerle kullanılabilir .

AC stili struct, bir bellek alanının düzenini tanımlayan bir tür şablondur (bir C ++ şablonu değil, bir desen veya şablon). Yıllar içinde C ve C eklentileri ile kullanılabilen arayüzler (burada Java ve Python ve Visual Basic'e bakıyoruz), bazıları C stili ile çalışıyor struct.


1

Teknik olarak her ikisi de C ++ 'da aynıdır - örneğin, bir yapının aşırı operatörlere sahip olması mümkündür.

Ancak :

Ben aynı anda birden çok türde bilgi aktarmak istediğinizde yapıları kullanmak "işlevsel" bir nesne ile uğraşırken ben sınıfları kullanın.

Umarım yardımcı olur.

#include <string>
#include <map>
using namespace std;

struct student
{
    int age;
    string name;
    map<string, int> grades
};

class ClassRoom
{
    typedef map<string, student> student_map;
  public :
    student getStudentByName(string name) const 
    { student_map::const_iterator m_it = students.find(name); return m_it->second; }
  private :
    student_map students;
};

Örneğin, burada get ... () yöntemlerinde bir yapı öğrencisi döndürüyorum - tadını çıkarın.


1

Struct'ı ne zaman kullanmayı ve C ++ 'da sınıfı ne zaman kullanmayı seçersiniz?

Kullandığım structtanımlamam zaman functorsve POD. Aksi takdirde kullanıyorum class.

// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
    bool operator()(int first, int second)
    { return first < second; }
};

class mycompare : public std::binary_function<int, int, bool>
{
public:
    bool operator()(int first, int second)
    { return first < second; }
};

1
Bu cevap yaş belirtileri gösteriyor :) std::binary_function<>sadece onaylanmamış değil, c ++ 17 bile kaldırıyor.
17'de 0:23

15 yıl önce tanımlanan bir dil olan C ++ 03 zamanında yazıldığı için gerçekten sürpriz değil.
Orbit'te Hafiflik Yarışları

1

POD tipi veya functor oluşturmam gerektiğinde yapılar kullanıyorum.


1

Tüm sınıf üyeleri varsayılan olarak özeldir ve tüm yapı üyeleri varsayılan olarak herkese açıktır. Sınıfın varsayılan özel tabanları ve Struct varsayılan ortak tabanları vardır. C durumunda yapı üye işlevlerine sahip olamaz, burada C ++ durumunda olduğu gibi yapıya üye işlevlerini ekleyebiliriz. Bu farklılıklar dışında, onlar hakkında şaşırtıcı bir şey bulamıyorum.


0

Yapıyı yalnızca ilişkili bazı üye işlevleri olmadan (üye verileri üzerinde çalışmak için) ve veri değişkenlerine doğrudan erişmek için bazı verileri tutmam gerektiğinde kullanıyorum.

Örn: Dosyalardan ve soket akışlarından veri okuma / yazma vb. Fonksiyon argümanlarının çok fazla olduğu ve fonksiyon sözdiziminin çok uzun olduğu bir yapıda fonksiyon argümanlarını iletme.

Teknik olarak, varsayılan erişilebilirlik dışında sınıf ve strütür arasında büyük bir fark yoktur. Daha fazlası programlama tarzını nasıl kullandığınıza bağlıdır.


-4

Ben Yapılar bir Veri Yapısı (bir çok veri tipi bilgi dizisi gibi) olarak tasarlandığını ve sınıflar Kod Paketleme (alt rutin ve fonksiyon koleksiyonları gibi) için inted olduğunu düşündüm.

:(


-6

C ++ 'da asla "struct" kullanmıyorum.

İsteyerek kafa karıştırmaya çalışmadığınız sürece, özel üyeler istediğinizde bir yapı kullanacağınız bir senaryo hayal bile edemiyorum.

Yapıları kullanmak, verilerin nasıl kullanılacağına dair sözdizimsel bir göstergedir, ancak sadece bir sınıf yapmak ve bunu sınıf adına veya yorumlarla açık hale getirmeyi tercih ederim.

Örneğin

class PublicInputData {
    //data members
 };

Bana göre, "verinin nasıl kullanılacağına dair sözdizimsel bir gösterge", özellikle alternatif, sınıf adında bir yorum veya ad kullanmaksa, bir yapı kullanmak için mükemmel bir nedendir.
Viktor Sehr

2
structSınıf üyelerinin varsayılan olarak herkese açık olacağı konusunda açık bir açıklama yapmak istemez miydiniz ?
yanlış kullanıcı adı
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.