سؤال

في سيناريوهات ما هو أفضل لاستخدام struct vs a class في C++?

هل كانت مفيدة؟

المحلول

الاختلافات بين class و struct في C++ هي التي البنيات يكون الافتراضي public أعضاء و القواعد و الفصول الافتراضية private أعضاء و القواعد.كل دروس و البنيات يمكن أن يكون خليط من public, protected و private أعضاء, يمكن استخدام الميراث و يمكن أن يكون لها وظائف الأعضاء.

أود أن أوصي باستخدام البنيات عادي-القديم-هياكل البيانات دون أي فئة ميزات مثل ، واستخدام الطبقات كما الكلي هياكل البيانات مع private البيانات ووظائف الأعضاء.

نصائح أخرى

الجميع يلاحظ أن هناك اثنين فقط الفعلية الاختلافات اللغوية:

  • struct التخلف إلى وصول الجمهور ، class التخلف إلى الوصول إلى القطاع الخاص.
  • عندما الميراث ، struct الافتراضي public الميراث و class الافتراضي private الميراث.(ومن المفارقات, كما هو الحال مع العديد من الأشياء في C++ ، الافتراضي إلى الوراء: public الميراث هو إلى حد بعيد الأكثر شيوعا الاختيار ، ولكن الناس نادرا ما تعلن structs فقط لانقاذ على كتابة "public"الكلمات الرئيسية.

ولكن الفرق الحقيقي في الممارسة بين class/struct يعلن منشئ/المدمر لا.هناك بعض الضمانات "عادي-القديم-البيانات" جراب نوع ، التي لم تعد تطبق مرة واحدة كنت تأخذ أكثر من فئة البناء.للحفاظ على هذا التمييز الواضح أن العديد من الناس عمدا فقط استخدام structs جراب أنواع ، و ، إذا أنهم ذاهبون إلى إضافة أي من طرق استخدام classes.الفرق بين شظايا أدناه وإلا لا معنى لها:

class X
{
  public:

  // ...
};

struct X
{
  // ...
};

(بالمناسبة هنا موضوع مع بعض التوضيحات حول ما "جراب نوع" يعني في الواقع: ما هي جراب أنواع في C++?)

هناك الكثير من المفاهيم الخاطئة في القائمة إجابات.

سواء class و struct تعلن فئة.

نعم ، قد تضطر إلى إعادة ترتيب الوصول تعديل الكلمات الرئيسية داخل الطبقة التعريف ، اعتمادا على الكلمات الرئيسية التي كنت تعلن الصف.

ولكن ما وراء الجملة ، فقط سبب اختيار واحد على الآخر هو الاتفاقية و/أو تفضيل.

بعض الناس يحبون أن العصا مع struct الكلمة لفئات دون وظائف الأعضاء, لأن الناتجة تعريف "يبدو" بنية بسيطة من C.

وبالمثل فإن بعض الناس ترغب في استخدام class الكلمة لفئات مع وظائف الأعضاء ، private البيانات, لأنه يقول "الطبقة" على ذلك وبالتالي يبدو أمثلة من المفضلة لديك كتاب عن البرمجة الشيئية.

الواقع هو أن هذا متروك لك تماما و فريقك و سوف تجعل حرفيا لا فرق على الإطلاق إلى البرنامج الخاص بك.

التالية فئتين هي مماثلة تماما في كل شيء ما عدا الاسم:

struct Foo
{
   int x;
};

class Bar
{
public:
   int x;
};

يمكنك حتى تبديل الكلمات عندما redeclaring:

class Foo;
struct Bar;

(على الرغم من أن هذه فواصل Visual Studio يبني بسبب عدم المطابقة ، حتى أن المترجم تنبعث من تحذير عند القيام بذلك.)

والعبارات التالية كلا تقييم صحيح:

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

ملاحظة, على الرغم من أنه لا يمكنك تبديل الكلمات عندما تعريف;هذا هو فقط لأن (لكل واحد-تعريف القاعدة) مكررة الدرجة التعاريف عبر الترجمة الوحدات "تتكون من نفس تسلسل من الرموز".وهذا يعني أنه لا يمكنك حتى تبادل const int member; مع int const member;, و لا علاقة له دلالات class أو struct.

المرة الوحيدة التي يمكنني استخدام البنية بدلا من فئة عندما أعلن functor قبل استخدامه في استدعاء دالة وتريد للحد من بناء الجملة من أجل التوضيح.على سبيل المثال:

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

من C++ التعليمات لايت:

أعضاء و الفئات الأساسية من البنية العامة بشكل افتراضي ، بينما في فئة الافتراضية الخاصة.ملاحظة:يجب أن تجعل النظام الخاص بك قاعدة الطبقات صراحة عامة أو خاصة أو محمية ، بدلا من الاعتماد على التخلف.

البنية و الدرجة هي على خلاف ذلك وظيفيا.

حسنا, يكفي أن نظيف تكنو الحديث.عاطفيا معظم المطورين جعل قوية التمييز بين فئة البنية.البنية ببساطة يشعر وكأنه مفتوح كومة من القطع مع القليل جدا في طريقة التغليف أو وظيفة.فئة يشعر وكأنه يعيش و عضو مسؤول في المجتمع مع الخدمات الذكية القوية التغليف الحاجز ، وكذلك تعريف واجهة.منذ ذلك دلالة معظم الناس لديهم بالفعل, ربما يجب عليك استخدام البنية الكلمة إذا كان لديك فئة لديها عدد قليل جدا من طرق العامة البيانات (مثل هذه الأشياء موجودة في تصميم أنظمة!), ولكن على خلاف ذلك ربما يجب عليك استخدام فئة رئيسية.

مكان واحد حيث البنية كانت مفيدة بالنسبة لي هو عندما يكون لدي نظام تلقي ثابت تنسيق الرسائل (على قول المنفذ التسلسلي) من نظام آخر.يمكنك أن يلقي تيار بايت في البنية التي تحدد الحقول ، ثم الوصول بسهولة إلى الحقول.

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);
}

ومن الواضح أن هذا هو نفس الشيء الذي كنت ستفعله في ج ، ولكن أجد أن النفقات العامة من الحاجة إلى فك الرسالة إلى فئة عادة لا يستحق ذلك.

يمكنك استخدام "البنية" في C++ إذا كنت تكتب مكتبة الذين الداخلية هي C++ ولكن API يمكن استدعاؤها من قبل سواء C أو C++ code.يمكنك ببساطة جعل رأس واحدة يحتوي على البنيات والعالمية وظائف API التي تعرض كل من C و C++ رمز مثل هذا:

// 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

ثم يمكنك كتابة دالة بار() في C++ الملف باستخدام C++ رمز وجعلها للاستدعاء من C العالمين يمكن تبادل البيانات من خلال أعلنت البنية ؟ هناك محاذير أخرى بالطبع عند خلط C و C++ ولكن هذا هو مثال مبسط.

كل واحد يقول الفرق الحقيقي الوحيد هو الوصول الافتراضية.ولكن أنا لا سيما استخدام البنية عندما لا تريد أي نوع من التغليف مع بيانات بسيطة الدرجة ، حتى إذا كنت تنفيذ بعض الطرق المساعد.على سبيل المثال, عندما كنت بحاجة الى شيء من هذا القبيل:

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

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

البنيات (القرون, أكثر عموما) هي في متناول يدي عندما كنت في توفير ج-واجهة متوافقة مع تنفيذ C++, منذ أنهم المحمولة عبر اللغة الحدود رابط الأشكال.

إذا هذا ليس مصدر قلق لك ، ثم أفترض استخدام "البنية" بدلا من "الطبقة" هو محاورا جيدا نوايا (كما @ZeroSignal ذكر أعلاه).البنيات أيضا أكثر قابلية للتنبؤ نسخ دلالات ، لذا فهي مفيدة بيانات كنت تنوي الكتابة إلى وسائل الإعلام الخارجية أو ترسل عبر الأسلاك.

البنيات هي أيضا في متناول اليد لمختلف metaprogramming المهام مثل الصفات القوالب التي تعرض فقط حفنة من يعتمد typedefs:

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

ولكن هذا هو حقا مجرد الاستفادة من البنية الافتراضية مستوى الحماية العامة...

C++, حقا ليس هناك الكثير من الفرق بين البنيات و الطبقات.الرئيسية وظيفية الفرق هو أن أعضاء من البنية العامة بشكل افتراضي ، في حين أنها خاصة افتراضيا في الطبقات.وإلا بقدر ما هي اللغة المعنية ، فهي ما يعادلها.

أنه قال: أنا أميل إلى استخدام البنيات في C++ كما أفعل في C# ، على غرار ما بريان قال.البنيات بسيطة البيانات الحاويات ، في حين أن الطبقات تستخدم الكائنات التي تحتاج إلى العمل على البيانات بالإضافة إلى يتمسكون به.

للإجابة على سؤالي (دون خجل) ، كما سبق ذكره ، امتيازات الوصول هي الفرق الوحيد بينهما في C++.

أنا أميل إلى استخدام البنية على تخزين البيانات فقط.سوف تسمح لها أن تحصل على عدد قليل من وظائف المساعد إذا كان يجعل العمل مع البيانات أسهل.ومع ذلك بمجرد أن البيانات يتطلب التحكم في التدفق (أيحاصل/المحددات التي تحافظ على أو حماية داخلية الدولة) أو يبدأ acquring أي وظائف رئيسية (في الأساس أكثر من موضوع مثل), وسوف تحصل على "ترقية" إلى فئة على التواصل بشكل أفضل النوايا.

فهي الى حد كبير نفس الشيء.بفضل سحر C++, البنية يمكن أن تعقد وظائف استخدام الميراث ، التي تم إنشاؤها باستخدام "الجديد" على مثل صف

وظيفية الوحيد الفرق هو أن الصف يبدأ مع وصول خاص الحقوق ، في حين أن البنية يبدأ مع الجمهور.هذا هو الحفاظ على التوافق مع C.

في الواقع ، لقد استعملت دائما البنيات البيانات أصحاب الطبقات كما الكائنات.

فئة.

أعضاء الفئة الخاصة بشكل افتراضي.

class test_one {
    int main_one();
};

ما يعادل

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

حتى إذا كنت في محاولة

int two = one.main_one();

سوف تحصل على خطأ: main_one is private لأنه لا يمكن الوصول إليها.يمكننا حل ذلك عن طريق تهيئة ذلك عن طريق تحديد عام أي

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

البنية.

البنية هي فئة فيها الأعضاء الجمهور بشكل افتراضي.

struct test_one {
    int main_one;
};

يعني main_one خاصة ie

class test_one {
  public:
    int main_one;
};

يمكنني استخدام البنيات عن هياكل البيانات حيث يمكن أن تأخذ أي قيمة ، إنه أسهل بهذه الطريقة.

هم نفس الشيء مع مختلف التخلف (خاص افتراضيا class, و الجمهور بشكل افتراضي struct) ، وذلك في نظرية انهم للتبادل تماما.

لذا ، إذا أريد فقط أن حزمة بعض المعلومات للتحرك ، يمكنني استخدام البنية ، حتى لو وضعت عدد قليل من الطرق هناك (ولكن ليست كثيرة).إذا كان الغالب-مبهمة الشيء ، حيث الاستخدام الرئيسي سيكون عبر أساليب غير مباشرة إلى أعضاء البيانات, استخدام فئة كاملة.

البنيات افتراضيا لديك وصول الجمهور وفئات افتراضيا لديك الوصول إلى القطاع الخاص.

أنا شخصيا استخدام البنيات لنقل البيانات الكائنات أو قيمة الأشياء.عندما تستخدم على هذا النحو أعلن جميع أعضاء const لمنع تعديل التعليمات البرمجية الأخرى.

ميزة struct أكثر class هو أنه حفظ سطر واحد من التعليمات البرمجية ، إذا كان الانضمام إلى "العام الأول أعضاء ، ثم القطاع الخاص".في ضوء ذلك وجدت الكلمة class عديمة الفائدة.

هنا سبب آخر لاستخدام فقط struct و لم class.بعض التعليمات البرمجية أسلوب مبادئ توجيهية C++ تشير إلى استخدام الحروف الصغيرة على وظيفة وحدات الماكرو ، والسبب أنه عندما الماكرو يتم تحويلها إلى وظيفة مضمنة اسم لا تحتاج إلى تغيير.نفس الشيء هنا.لديك لطيفة ج-نمط البنية و في يوم تكتشف أنك تحتاج إلى إضافة منشئ أو بعض الراحة الأسلوب.هل تغييره إلى class?في كل مكان ؟

التمييز بين structs classes هو مجرد الكثير من المتاعب ، تحصل في الطريق من القيام بما يجب علينا فعله - البرمجة.مثل الكثير من C++'s المشاكل ، فإنه ينشأ من رغبة قوية في الوراء التوافق.

من الناحية الفنية على حد سواء هي نفسها في C++ - على سبيل المثال فإنه من الممكن البنية أن يكون طاقتها مشغلي الخ.

ومع ذلك :

يمكنني استخدام البنيات عندما كنت ترغب في تمرير المعلومات من أنواع متعددة في وقت واحد يمكنني استخدام الطبقات عندما أتعامل مع "وظيفية" الكائن.

آمل أن يساعد.

#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;
};

على سبيل المثال, أنا أرد على البنية الطالب في الحصول على...() أساليب هنا - التمتع بها.

عندما تختار لاستخدام البنية و عند استخدام فئة في C++?

يمكنني استخدام struct عندما تحدد functors و POD.وإلا لم تستخدم 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; }
};

يمكنني استخدام البنيات عندما كنت في حاجة إلى إنشاء جراب نوع أو functor.

جميع أعضاء الفئة الخاصة بشكل افتراضي و كل البنية أعضاء الجمهور بشكل افتراضي.الصف الافتراضي الخاص أسس البنية الافتراضية القواعد العامة.البنية في حالة C لا يمكن أن يكون وظائف الأعضاء فيها كما هو الحال في C++ نحن يمكن أن يكون لها وظائف الأعضاء إضافة إلى البنية.البعض من هذه الاختلافات ، أنا لا أجد أي شيء يثير الدهشة حول لهم.

كما أشار آخرون

  • كلاهما يعادل وبصرف النظر عن الرؤية الافتراضية
  • قد يكون هناك أسباب يضطر إلى استخدام واحدة أو أخرى لأي سبب من الأسباب

هناك توصية واضحة حول متى يمكن استخدام أي من Stroustrup/سوتر:

استخدام الدرجة إذا كانت فئة لديها ثابتة;استخدام البنية إذا كان أعضاء البيانات يمكن أن تختلف بشكل مستقل

لكن, نضع في اعتبارنا أنه ليس من الحكمة أن الأمام تعلن sth.كفئة (class X;) و تعرف على أنها البنية (struct X { ... }).قد تعمل على بعض linkers (على سبيل المثال ، g++) و قد تفشل على الآخرين (على سبيل المثال ، MSVC) ، لذلك سوف تجد نفسك في المطور الجحيم.

يمكنني استخدام البنية فقط عندما كنت في حاجة إلى عقد بعض البيانات دون أي وظائف الأعضاء المرتبطة بها (تعمل على الأعضاء البيانات) والوصول إلى البيانات المتغيرات مباشرة.

على سبيل المثال:قراءة/كتابة البيانات من الملفات مأخذ تيارات الخ.يمر الحجج وظيفة في الهيكل حيث وظيفة حجج كثيرة وظيفة الجملة تبدو طويلة جدا.

عمليا ليس هناك فرق كبير بين فئة struture إلا الافتراضية إمكانية الوصول.أكثر أكثر من ذلك يعتمد على أسلوب البرمجة كيفية استخدامه.

ظننت أن البنيات كان المقصود هيكل البيانات (مثل متعدد نوع البيانات مجموعة من المعلومات) والطبقات كان inteded على رمز التعبئة والتغليف (مثل مجموعات من الوظائف الفرعية والوظائف)..

:(

لم أكن استخدام "البنية" في C++.

لا أستطيع تخيل سيناريو حيث يمكنك استخدام البنية عندما تريد من الأعضاء ما لم تكن عمدا يحاول أن يكون مربكا.

يبدو أن استخدام البنيات أكثر النحوية إشارة إلى كيفية استخدام البيانات ، ولكن أود أن بدلا من مجرد جعل فئة ومحاولة لجعل هذا صريح في اسم الفئة أو من خلال التعليقات.

E. g.

class PublicInputData {
    //data members
 };
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top