على كتابة المجمع Win32 المعهد مع C ++، كيفية تمرير هذا المؤشر إلى وظيفة ثابتة

StackOverflow https://stackoverflow.com/questions/412183

  •  03-07-2019
  •  | 
  •  

سؤال

وأريد تحويل الكائن وظيفة إلى وظيفة.

ولقد كتبت هذا الرمز، ولكنه لا يعمل.

#include <iostream>

typedef int (*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return this->*&adder::operator();
    }
};

int main(void) {
    adder add_two(2);
    int_to_int add_fn = add_two;
    std::cout << add_two(3) << std::endl; // expect 5
    std::cout << add_fn(3)  << std::endl; // expect 5
    add_fn = adder(5);
    std::cout << add_fn(3)  << std::endl; // expect 8
    return 0;
}

ووحصلت على رسالة من ز ++، يقول invalid use of non-static member function.

وكيف يمكنني الحصول على مؤشر إلى وظيفة عضو في المثال؟

تعديل : في. مشكلتي الأصلية حول Win32 وAPI

وأنا اضطررت لكتابة برنامج ويندوز مع API Win32 والقديم في المدرسة. لكنني لا أريد أن أكتب بيان التبديل الرهيبة مثل بعض رموز سبيل المثال في النص. ثم، قررت أن أكتب المجمع في C ++.

وأريد أن أكتب فئة الإطار مثل ...

class Window {
public:
    LRESULT update (HWND, UINT, WPARAM, LPARAM);
    void run();
    // below methods are called by update()
    virtual void onclick(int, int);
    virtual void ondraw(); // ... and more methods
};

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

وأخيرا يا probrem الفعلي هو كيفية القيام بذلك في C ++.

 // on initializing my window object,
 // I must register window class with callback which is 
 // not a C++ function object.
 // I try to explain what I want to do with psudocode mixing C++ and javascript.
 WNDCLASS wndclass;
 Window *self = this;
 wndclass.lpfnWndProc = function () {
     return self.update.apply(self, argunemts);
 };

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

تعديل : في العنوان الأصلي لهذه المسألة كان <م> كيفية الحصول على رمية لأعضاء وظيفة من الدرجة . ولكن هذا اللقب وسؤالي لم يقل لي المشكلة الفعلية بما فيه الكفاية. آسف لanswerers في وقت مبكر، وlitb، وأشكركم على اقتراح والإجابة مفيدة جدا!

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

المحلول

على تحديث : لقلت لنا ما تريد. لقد وجدت هذا السؤال هنا على SO: أفضل طريقة لتخزين هذا المؤشر لاستخدامها في WndProc . أنا لست ويندوز مبرمج، ولكن الرجل آدم روزنفيلد يبدو أن الحق في استخدام SetWindowLongPtr وGetWindowLongPtr. لذلك، يمكنك استخدام مثل هذا:

LRESULT CALLBACK my_callback(HWND hwnd, UINT ui, WPARAM wp, LPARAM lp) {
    Window * self = reinterpret_cast<Window*>(
        GetWindowLongPtr(hwnd, 0));
    return self->update(hwnd, ui, wp, lp); // handle it.
}

وسجل أن وظيفة مثل WND-بروك وتخزين مؤشر this من الكائن إطار باستخدام SetWindowLongPtr. في بنية WNDCLASSEX، هناك حقل cbWndExtra التي تقوم بتعيينها sizeof(Window*) ل، وهو تخزين كافية لاحتواء فقط هذا المؤشر. ثم يمكنك الاتصال

SetWindowLongPtr(my_hwnd, 0, reinterpret_cast<LONG_PTR>(this));

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


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

struct adder;
typedef int (adder::*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return &adder::operator();
    }
};

والآن، لا بل يعتبر عامل التحويل، لأنه يحتوي على تسميته مثل هذا:

adder a(10); cout << (a.*(int_to_int)a)(2); // expected: 12

ويدويا مثل هذا:

// note, we just get the member function pointer using the conversion operator.
// Nothing is related to the actual temporary adder object. 
int_to_int i = adder(5);
cout << (adder(10).*i)(2); // expected: 12

وبناء الجملة استدعاء دالة المعتاد لا تعامل مع ذلك. باختصار، ما حاولت غير ممكن.

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

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
};

adder a(10); cout << a(2); // expected: 12

نصائح أخرى

وطريقة مثيل مؤشرات هي صعبة بعض الشيء، وهي حوش مختلفة تماما مقارنة مع مؤشرات الدالة "عادية".

وانظر ما C ++ التعليمات ايت القسم 33 لديه ليقوله عن ذلك. انظر أيضا هذا و <لأ href = "HTTP: //www.codeproject كوم / KB / حزب الشعب الكمبودي / FastDelegate.aspx "يختلط =" نوفولو noreferrer "> هذا للحصول على أمثلة ملموسة.

ومؤشر إلى دالة عضو nonstatic يختلف عن مؤشر إلى وظيفة ثابتة (أو إلى وظيفة العالمية، وبالتالي ثابتة) لأن أعضاء nonstatic يكون خفية "هذا" المعلمة.

ونوع لغلوبالس أو احصائيات شيء من هذا القبيل الباحث (*) (الباحث)

ولكن، ونوع لnonstatic شيء من هذا القبيل الباحث (اسم_الفئة :: *) (الباحث).

وأن يقال، رمز لديه أشياء أغرب فيه، منذ يبدو أنك تكون محاولة لتعيين المنشئ أو كائن شيدت في مؤشر الدالة.

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