سؤال

هل هناك طريقة أفضل لتأسيس إزاحة المناعة لعضو بيانات الكائن أكثر من ما يلي؟

class object
{
  int a;
  char b;
  int c;
};

object * o = new object();
int offset = (unsigned char *)&(object->c) - (unsigned char *)o;
delete o;
هل كانت مفيدة؟

المحلول

في هذه الحالة، صفك جراب، حتى تتمكن من استخدام offsetof ماكرو من <cstddef>.

في الممارسة العملية، في معظم التطبيقات، بالنسبة لمعظم الفصول، يمكنك استخدام نفس الخدعة التي تستخدمها الأوفستوف عادة:

int offset = &(((object *)0)->c) - (object *)0;

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

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

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

نصائح أخرى

ليست هناك حاجة لإنشاء كائن فعليا:

(size_t)&(((object*)0)->c)

وهذا هو، عنوان عضو في كائن في العنوان صفر هو إزاحة هذا العضو في الكائن.

بالطبع، سوف تحتاج إلى الوصول إلى العضو، لذلك تحتاج إما أن تجعلها struct أو أضف أ public: الوصول الى المعدل.

هذه هي الطريقة offsetof يتم تنفيذها، على الأقل بالنسبة لمعظم المترجمين.

بدلا من مؤشر.
يمكنك استخدام مؤشر إلى عضو.

class X;
typedef int X::*    PtrToMemberInt;  // Declare a pointer to member.

class X
{
    int a;
    char b;
    float c;

    public:
    static PtrToMemberInt   getAPtr()
    {
        return &X::a;
    }

    int d;
};

int main()
{
    // For private members you need to use a public method to get the address.
    PtrToMemberInt aPtr = X::getAPtr();

    // For public members you can take the address directly;
    PtrToMemberInt dPtr = &X::d;


    // Use the pointer like this:
    X   a;
    a.*aPtr = 5;
    a.*dPtr = 6;
}

للإضافة إلى Andins Answer، كما هو مذكور في "تصميم وتطور C ++" بواسطة StraStrup (القسم [13.11]):

لقد أثبت مؤشرات أعضاء البيانات طريقة مفيدة للتعبير عن تخطيط فئة C ++ في تنفيذ [Hübel، 1992

كان Sandeep لطيف جدا لتحويل الورق الأصلي وجعله متاح http://sandeep.files.wordpress.com/2008/07/ps.pdf.

لاحظ أن التنفيذ الموضح تم إعداده C ++ RTTI، لكنني ما زلت في بعض الأحيان استخدام الأشياء المؤشر إلى الأعضاء.

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