c++ - كيفية تحديد منصة / مترجم من وحدات الماكرو preprocessor؟




macros cross-platform c-preprocessor (5)

أنا أقوم بكتابة كود عبر النظام الأساسي ، والذي يجب أن يتم تجميعه في linux ، windows ، Mac OS. على النوافذ ، يجب أن أقوم بدعم الاستوديو البصري و mingw.

هناك بعض أجزاء من التعليمات البرمجية الخاصة #ifdef .. #endif الأساسي ، والتي يجب وضعها في #ifdef .. #endif بيئة. على سبيل المثال ، لقد وضعت هنا رمزًا خاصًا بـ win32:

#ifdef WIN32
#include <windows.h>
#endif

ولكن كيف يمكنني التعرف على linux و Mac OS؟ ما الذي يحدد الأسماء (أو غيرها) التي ينبغي علي استخدامها؟


Answers

انظر: http://predef.sourceforge.net/index.php

يوفر هذا المشروع قائمة شاملة بشكل معقول من #defines محددة #defines للعديد من أنظمة التشغيل ، #defines ، ومعايير اللغة والمنصة ، والمكتبات القياسية.


إليك ما أستخدمه:

#ifdef _WIN32 // note the underscore: without it, it's not msdn official!
    // Windows (x64 and x86)
#elif __unix__ // all unices, not all compilers
    // Unix
#elif __linux__
    // linux
#elif __APPLE__
    // Mac OS, not sure if this is covered by __posix__ and/or __unix__ though...
#endif

تحرير: على الرغم من أن ما سبق قد يعمل على الأساسيات ، تذكر أن تتحقق من الماكرو الذي تريد التحقق منه من خلال النظر في الصفحات المرجعية Boost.Predef . أو مجرد استخدام Boost.Predef مباشرة.


لنظام التشغيل Mac :

#ifdef __APPLE__

لـ MingW على نظام Windows:

#ifdef __MINGW32__

لنظام التشغيل Linux :

#ifdef __linux__

لمترجمات Windows الأخرى ، تحقق من هذا الموضوع this لعدة معجبي وأبنية أخرى.


إذا كنت تكتب C ++ ، فلا يمكنني التوصية باستخدام مكتبات Boost بقوة كافية.

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

#include <boost/predef.h>

// ...

#if BOOST_OS_WINDOWS

#elif BOOST_OS_LINUX

#elif BOOST_OS_MACOS

#endif

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

لذا للتخلص من الارتباك أولاً: نعم ، يمكن تجاوز الدالات الظاهرية الخاصة في الطبقات المشتقة. لا يمكن للطرق المشتقة من الفئات استدعاء وظائف ظاهرية من الفئة الأساسية ، ولكن يمكنها توفير التنفيذ الخاص بها. وفقاً لـ Herb Sutter ، فإن وجود واجهة عامة غير افتراضية في الطبقة الأساسية وتطبيق خاص يمكن تخصيصه في الفئات المشتقة ، يسمح بتحسين "فصل مواصفات الواجهة عن مواصفات السلوك القابل للتخصيص للتنفيذ". يمكنك قراءة المزيد حول هذا الموضوع في مقالته "Virtuality" .

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

"Overloaded Non-Virtuals العامة Call Protected Non-Overloaded Virtuals"

يساعد على إدارة قاعدة إخفاء بشكل صحيح . يمكنك قراءة المزيد عنها here ، ولكن سأحاول شرحها بعد قليل.

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

class Engine
{
public:
    virtual void SetState( int var, bool val ) {/*some implementation*/}
    virtual void SetState( int var, int val )  {/*some implementation*/}
};

لنفترض الآن أنك تريد إنشاء فئة مشتقة وتحتاج إلى توفير تطبيق جديد للأسلوب فقط ، والذي يأخذ اثنين من النتوءات كوسيطة.

class MyTurbochargedV8 : public Engine
{
public:
    // To prevent SetState( int var, bool val ) from the base class,
    // from being hidden by the new implementation of the other overload (below),
    // you have to put using declaration in the derived class
    using Engine::SetState;

    void SetState( int var, int val )  {/*new implementation*/}
};

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

MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);

إذا لم تمنع إخفاء أعضاء Engine ، فإن العبارة:

myV8->SetState(5, true);

سوف يطلق void SetState( int var, int val ) من الطبقة المشتقة ، يحول true إلى int .

إذا كانت الواجهة ليست افتراضية والتطبيق الافتراضي غير عام ، كما هو الحال في exmaple ، فإن مؤلف الطبقة المشتقة لديه مشكلة واحدة أقل للتفكير فيها ويمكن ببساطة كتابة

class MyTurbochargedV8 : public Engine
{
private:
    void SetStateInt(int var, int val )  {/*new implementation*/}
};




c++ macros cross-platform c-preprocessor