سؤال

هل هناك أي طريقة لإضافة حقل إلى الفئة في وقت التشغيل ( الميدان التي لم تكن موجودة من قبل ) ?شيء مثل هذا مقتطف :

Myobject *ob; // create an object
ob->addField("newField",44); // we add the field to the class and we assign an initial value to it
printf("%d",ob->newField); // now we can access that field

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

مثال آخر: أقول لدي ملف XML التي تصف هذه الفئة :

<class name="MyClass">
   <member name="field1" />
   <member name="field2" />
</class>

وأريد أن "إضافة" الحقول "field1 ومن" و "field2" إلى فئة (على افتراض الفئة موجودة بالفعل) .دعنا نقول هذا هو رمز الفئة :

class MyClass {
};

أنا لا أريد أن إنشاء الفئة في وقت التشغيل ، أنا فقط أريد أن أضيف أعضاء/الحقول الحالية .

شكرا لك !

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

المحلول

استخدام خريطة البديل.

على سبيل المثال باستخدام دفعة::البديل.انظر http://www.boost.org/doc/libs/1_36_0/doc/html/variant.html

(ولكن بالطبع يمكنك إنشاء الخاصة بك لتناسب أنواع من سمات XML.)

#include <map>
#include <boost/variant.hpp>

typedef boost::variant< int, std::string > MyValue ;
typedef std::map<std::string, MyValue> MyValueMap ;

عن طريق إضافة MyValueMap عضوا في الفئة الخاصة بك ، يمكنك إضافة خصائص وفقا أسمائهم.مما يعني رمز:

oMyValueMap.insert(std::make_pair("newField", 44)) ;
oMyValueMap.insert(std::make_pair("newField2", "Hello World")) ;
std::cout << oMyValueMap["newField"] ;
std::cout << oMyValueMap["newField2"] ;

عن طريق التغليف في MyObject الدرجة ، إضافة حق طاقتها accessors في هذا MyObject الدرجة رمز أعلاه يصبح أكثر وضوحا إلى حد ما:

oMyObject.addField("newField", 44) ;
oMyObject.addField("newField2", "Hello World") ;
std::cout << oMyObject["newField"] ;
std::cout << oMyObject["newField2"] ;

ولكن تفقد إلى حد ما نوع من سلامة C++ القيام بذلك.ولكن XML, هذا أمر لا مفر منه, أعتقد.

نصائح أخرى

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

ولكن انظر العالمية نمط تصميم.

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

template< typename T > T get_member( string name );
template< typename T > void set_member( string name, T value );

هل يمكن أن تجعل الجملة أكثر إحكاما/صعبة إذا كنت تريد (على سبيل المثال:باستخدام '->' المشغل تجاوز).هناك أيضا بعض مترجم-الحيل محددة يمكن أن الرافعة المالية (MSVC يدعم __declspec(الملكية) ، على سبيل المثال ، والذي يسمح لك لتعيين مراجع عضو متغير أساليب صيغة محددة).في نهاية اليوم, على الرغم من أنك لن تكون قادرة على فعل شيء المترجم لا يقبل في اللغة والحصول على ترجمة.

النسخة القصيرة: لا يمكن أن تفعل ذلك.لا يوجد دعم أصلي من أجل هذا, c++ هو كتابتها بشكل ثابت ، مترجم يجب أن يعلم بنية كل كائن يتم التلاعب بها.

التوصية: استخدام جزءا لا يتجزأ من interperter.و لا الكتابة الخاصة بك (انظر أدناه), الحصول على واحد أن يعمل بالفعل و تصحيحه.


ما يمكنك القيام به: تنفذ فقط ما يكفي interperter لتلبية الاحتياجات الخاصة بك.

سيكون بسيطا بما فيه الكفاية إلى إعداد فئة مع بيانات العضو مثل

std::vector<void*> extra_data;

التي يمكن أن نعلق التعسفي البيانات في وقت التشغيل.تكلفة هذا هو أنه سيكون لديك لإدارة البيانات باليد مع أساليب مثل:

size_t add_data_link(void *p); // points to existing data, returns index
size_t add_data_copy(void *p, size_t s) // copies data (dispose at
                                        // destruction time!), returns 
                                        // index 
void* get_data(size_t i); //...

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

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

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

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

struct AnyMap {
  void addAnyPair( const std::string& key , boost::any& value );

  template<typename T>
  T& get( const std::string key ) {
    return( boost::any_cast<T&>(map_[key]) );
  }

  std::map<const std::string, boost::any> map_;
};

void AnyMap::addAnyPair( const std::string& key , boost::any& value ) {
  map_.insert( std::make_pair( key, value ) );
}

خلاصة القول هذا هو الإختراق, منذ C++ صارمة نوع التحقق اللغة ، وبالتالي الوحش تكمن في تلك التي تخرق القواعد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top