سؤال

ولدي رمز مشابهة لهذه في التطبيق الخاص بي:

class A
{
  public: int b;
}

class C
{
  public: int d;
}

void DoThings (void *arg1, MYSTERYTYPE arg2);

A obj_a;
C obj_c;

DoThings(&obj_a, &A::b);
DoThings(&obj_c, &C::d);

والسؤال هو - ما الذي يجب MYSTERYTYPE يكون؟ لا باطل * ولا كثافة العمل، على الرغم من قيمة & A :: ب تتم طباعتها على ما يرام إذا كنت إخراجه من خلال printf.

وتوضيحات: نعم، يتم تعريف & A :: ب تحت C ++. نعم، وأنا أحاول الحصول على تعويض لعضو الفئة. نعم، أنا كونها صعبة.

وتحرير: يا أنا يمكن استخدام offsetof (). على أي حال شكرا.

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

المحلول

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

struct a { int c; }; struct b : a { }; int main() { int b::*d = &a::c; }

على تحديث : لأنني أعتقد أنني يجب أن تكتب لماذا اعتنقوا أعلاه من a::* إلى b::* ضمنا. بعد كل شيء، ونحن عادة ما يكون b* إلى a*! النظر فيما يلي:

struct a { };
struct b : a { int c; };
struct e : a { };
int main() { int a::*d = &b::c; e e_; (e_.*d) = 10; /* oops! */ }

وإذا كان ما سبق سيكون ساري المفعول، وكنت حقا المسمار كثيرا ما يصل. ما سبق هو لا صالحة، لأن التحويل من b::* إلى a::* ليس الضمني. كما ترون، نحن تعيين المؤشر إلى b :: ج، ومن ثم يمكننا أن dereference باستخدام فئة التي لا تحتوي على الإطلاق! (e). المترجم يفرض هذا النظام:

int main() { int b::*d = &b::c; e e_; (e_.*d) = 10; /* bug! */ }

وو<م> فشل لتجميع الآن، لأنه لم يتم المستمدة e من b، وصنف مؤشر مؤشر عضوا ينتمي إليها. حسن! وفيما يلي، ومع ذلك، هو صحيح جدا ويجمع، وبطبيعة الحال (تغير فصول a وb):

struct a { int c; };
struct b : a { };
struct e : a { };
int main() { int e::*d = &a::c; e e_; (e_.*d) = 10; /* works! */ }

لجعلها تعمل لقضيتك، لديك لجعل الدالة قالب:

template<typename Class>
void DoThings (int Class::*arg) { /* do something with arg... */ }

والآن، ومترجم لصناعة السيارات في استدلال على الدرجة المناسبة أن المؤشر عضو معين ينتمي أيضا. سيكون لديك لتمرير سبيل المثال جنبا إلى جنب مع المؤشر الأعضاء على فعلا الاستفادة منه:

template<typename Class>
void DoThings (Class & t, int Class::*arg) { 
    /* do something with arg... */ 
    (t.*arg) = 10;
}

إذا كنت ترغب فقط في تعيين بعض أعضاء تعلمون في ذلك الوقت أن تكتب DoThings، وفيما يلي يكفي:

template<typename Class>
void DoThings (Class & t) {  
    t.c = 10;
}

نصائح أخرى

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

وإلا، إذا كنت حقا تحاول أن تفعل شيئا صعبة تتطلب C ++ الصورة غريب مرفق مؤشر لأعضاء (وكنت شبه المؤكد لا):

ومنذ الطبقات A وC لا علاقة لها، وسوف تحتاج إلى وظيفة قالب للتعامل مع كل من:

template <typename T>
void DoThings(int T::*x);

إذا كانت مستمدة في الواقع من C A، فإن ما يلي يعمل:

void DoThings(int A::*x);

& A :: B و C و:: د لا معنى لها، لا يوجد عنوان المرتبطة بها. هل تحاول الحصول على تعويض من الأعضاء؟

هل أنت متأكد أنك لا تريد شيئا كما يلي؟

DoSomething(&obj_a,&obj_a.b);

إذا كنت تستخدم القوالب كما يقترح j_random_hacker، ومترجم يعرف نوع كل فئة في مكان استدعاء وظيفة، والجواب الحرفي لسؤالك هو "template <typename CLASS> void DoThings (CLASS * object, int CLASS::*MEMBER)".

وهنا هو كيف يمكن ان تندرج في المثال الخاص بك:

#include <iostream>

class A {
public: 
    int b;
};

class C {
public: 
    int d;
};

template <typename CLASS>
void DoThings (CLASS * object, int CLASS::*MEMBER)
{
    std::cout << object->*MEMBER << std::endl;
}

A obj_a = { 2 };
C obj_c = { 4 };

int main (int argc, const char * argv[])
{
    DoThings(&obj_a, &A::b);
    DoThings(&obj_c, &C::d);
    return 0;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top