سؤال

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

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

ما لا يعني هو مؤشر إلى وظيفة عضو من فئة.E. G.

int (Fred::*)(char,float)

كان من المفيد جدا و جعل حياتي أسهل.

هوغو

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

المحلول

@RocketMagnet - هذا هو الرد على سؤال آخر, الذي وصفت مكررة.أنا أجاوب على أن السؤال ليس هذا واحد.

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

#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};

int main() {
    typedef void (A::*pmf_t)();
    C c; c.x = 42; c.y = -1;

    pmf_t mf = static_cast<pmf_t>(&C::foo);
    (c.*mf)();
}

ترجمة هذا الكود البرمجي بحق يشكو:

$ cl /EHsc /Zi /nologo pmf.cpp
pmf.cpp
pmf.cpp(15) : warning C4407: cast between different pointer to member representations, compiler may generate incorrect code

$

حتى الإجابة "لماذا لا C++ لدي مؤشر إلى الأعضاء-الدالة على الفراغ الدرجة ؟" هو أن هذا وهمي قاعدة الطبقة من كل شيء لا يوجد لديه أعضاء ، لذلك ليس هناك قيمة يمكن بأمان تعيين ذلك!"الفراغ (C::)()" و "الفراغ (فراغ::)()" تكون غير متوافقة مع أنواع.

الآن أراهن أنك تفكر "انتظر, لقد يلقي عضو-وظيفة-مؤشرات على ما يرام قبل!" نعم ، قد يكون باستخدام reinterpret_cast واحد الميراث.هذا هو في نفس الفئة الأخرى تفسير يلقي:

#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};
class D { public: int z; };

int main() {
    C c; c.x = 42; c.y = -1;

    // this will print -1
    D& d = reinterpret_cast<D&>(c);
    cout << "d.z == " << d.z << "\n";
}

حتى إذا void (void::*)() لم توجد ، ولكن هناك شيء يمكنك بأمان/portably تعيين إلى ذلك.

تقليديا, يمكنك استخدام وظائف التوقيع void (*)(void*) في أي مكان كنت من استخدام void (void::*)(), لأنه بينما الأعضاء-وظيفة رميات لا يلقي جيدا صعودا وهبوطا الميراث heirarchy باطلا المؤشرات لا يلقي جيدا.بدلا من ذلك:

#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};

void do_foo(void* ptrToC){
    C* c = static_cast<C*>(ptrToC);
    c->foo();
}

int main() {
    typedef void (*pf_t)(void*);
    C c; c.x = 42; c.y = -1;

    pf_t f = do_foo;
    f(&c);
}

لذا على سؤالك.لماذا لا C++ دعم هذا النوع من الصب.مؤشر إلى الأعضاء-وظيفة أنواع بالفعل للتعامل مع الظاهرية vs غير ظاهري فئات أساسية ، الافتراضية مقابل غير ظاهري وظائف الأعضاء ، كل ذلك في نفس نوع تضخيم لهم 4*sizeof(الفراغ*) على بعض المنصات.أعتقد لأن هذا من شأنه أن يزيد من تعقيد تنفيذ المؤشر إلى الأعضاء-وظيفة الخام مؤشرات الدالة بالفعل حل هذه المشكلة جيدا.

كما علق آخرون, C++ يعطي مكتبة الكتاب ما يكفي من الأدوات للحصول على هذا عمله ، ثم 'العادية' المبرمجين مثلي و مثلك أن استخدام تلك المكتبات بدلا من التعرق هذه التفاصيل.

تحرير:شهد المجتمع ويكي.يرجى فقط تحرير تشمل المراجع ذات الصلة إلى C++ القياسية ، إضافة مائل.(esp.إضافة مراجع إلى مستوى حيث كان فهمي خاطئ!^_^ )

نصائح أخرى

كما أشار آخرون إلى, C++ لديها وظيفة عضو نوع مؤشر.

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

وبالمثل, C++ لا يوجد قفل{} بدائية مثل C#'s ولكن لديها RAII الذي يستخدم من قبل دفعة scoped_lock.

هناك بالطبع من يقول يجب إضافة جملة السكر عن كل ما قد يكون من الاستخدام.للأفضل أو للأسوأ, C++ لا تنتمي إلى تلك المدرسة.

أعتقد أن ما تبحث عنه قد يكون في هذه librairies...

سريع المندوبين http://www.codeproject.com/KB/cpp/FastDelegate.aspx

دفعة.وظيفة http://www.boost.org/doc/libs/1_37_0/doc/html/function.html

و ها هو شرح كامل من وظيفة مؤشر الأسئلة ذات الصلة http://www.parashift.com/c++-faq-lite/pointers-to-members.html

فإنه لا.

على سبيل المثال ،

int (Fred::*)(char,float)

هو مؤشر إلى وظيفة عضو من فئة Fred أن بإرجاع int ويأخذ char و float.

أعتقد أن الجواب هو أن مصممي C++ اختيار لا يكون في لغة الأشياء التي يمكن تنفيذها بسهولة في المكتبة.وصف الخاصة بك من ما تريد يعطي طريقة معقولة تماما لتنفيذ ذلك.

أعرف أن الأمر يبدو غريبا ، ولكن C++ هي اللغة أضيق الحدود.لم تترك المكتبات كل ما يمكن أن تترك لهم.

على TR1 وقد std::tr1::وظيفة ، وسيكون إضافة إلى C++0x.بمعنى أنه لا يكون ذلك.

واحدة من تصميم الفلسفات C++ هي:أنت لا تدفع ثمن ما كنت لا تستخدم.المشكلة مع C# ستايل delagates هو أنها ثقيلة وتتطلب دعم اللغة أن الجميع سيدفع سواء كانوا منهم أو لا.هذا هو السبب في مكتبة تنفيذ المفضل.

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

كل ما قال ، أنا لست مترجم الكاتب.فإنه قد يكون من الممكن تقديم نوع جديد من أجل الالتزام طريقة المؤشرات التي من شأنها تخريب الظاهري-نيس الأسلوب المشار إليه (بعد كل شيء نحن نعرف ما قاعدة الطبقة إذا كان الأسلوب لا بد).

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

(أبنية عادة استخدام TOC أن تخزين المحتويات مؤشر في مؤشر الدالة جزء وليس في صوت هائل ، كما أن القيام بالفعل.)

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

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

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

[تحرير:MSalters في تعليق على rocketmagnet آخر أعلاه يشير إلى أنه إذا كان كل جسم وظيفة معروفة ، ثم هذا ويقابل ذلك يمكن تحديد على الفور.هذا تماما لم يحدث لي!ولكن مع هذا في الاعتبار, أعتقد هناك حاجة فقط أن يتم تخزين الدقيق كائن مؤشر ربما تعوض الدقيقة وظيفة المؤشر.وهذا يجعل thunks لا لزوم لها تماما-أعتقد-ولكن أنا متأكد من أن قضايا لافتا إلى وظائف الأعضاء وغير الأعضاء الوظائف على حد سواء أن تبقى.]

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

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

هذا غير ممكن مع UDT.دفعة::وظيفة لا يمكن تجاهل النفقات العامة PTMF عندما يربط الكائن المؤشر.تحتاج إلى معرفة وفهم بنية PTMF, vtable ، إلى آخره - جميع غير القياسية الأشياء.ومع ذلك ، فإننا قد نصل الى هناك الآن مع C++1x.مرة واحدة في std::, انها لعبة عادلة مترجم البائعين.المكتبة القياسية تنفيذ حد ذاته ليس المحمولة (انظر على سبيل المثالtype_info).

كنت لا تزال تريد أن يكون بعض جميلة الجملة أعتقد حتى لو مترجم البائع بتنفيذ هذا في المكتبة.أود std::function<void(*)()> foo = &myX && X::bar.(لا صراع مع القائمة الجملة ، كما س::شريط ليس التعبير فقط &X::شريط)

يحدث لي أن أساليب ضمني this الحجة, لذلك c مؤشر إلى أسلوب غير كافية للسماح طريقة تسمى (لأنه لا توجد طريقة لتحديد سبيل المثال ينبغي أن تستخدم this (أو حتى لو أي المقام حاليا موجودة)).

تحرير: Rocketmagnet التعليقات التي وجهها هذا السؤال و الذي يظهر أن هذا هو الحال ، على الرغم من أنني أعتقد أن أضيف بعد أن بدأت هذه الاستجابة.ولكن سأقول "mea الإهمال" ، على أي حال.

لذلك اسمحوا لي أن التوسع في الفكر قليلا.

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

بالتأكيد يمكنك بناء نوع مشتق للقيام بهذه المهمة-كما في دفعة تنفيذ---ولكن مثل هذا المخلوق ينتمي في المكتبة.

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