سؤال

تعزيز الإشارات مكتبة، فإنها والحمولة الزائدة المشغل ().

هل هذه الاتفاقية في C ++؟ لالاسترجاعات، الخ.؟

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

وأي فكرة عن السبب في ذلك الزائد؟

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

المحلول

واحدة من الهدف الأساسي عند الحمولة الزائدة المشغل () هو خلق functor. A functor يتصرف تماما مثل وظيفة، لكنه لا يملك مزايا أنه جليل، وهذا يعني أنه يمكن الحفاظ على البيانات التي تعكس حالته بين المكالمات.

وهنا هو functor مثال بسيط:

struct Accumulator
{
    int counter = 0;
    int operator()(int i) { return counter += i; }
}
...
Accumulator acc;
cout << acc(10) << endl; //prints "10"
cout << acc(20) << endl; //prints "30"
تستخدم

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

template <typename InputIterator, typename Functor>
void for_each(InputIterator first, InputIterator last, Functor f)
{
    while (first != last) f(*first++);
}

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

void print(int i) { std::cout << i << std::endl; }
...    
std::vector<int> vec;
// Fill vec

// Using a functor
Accumulator acc;
std::for_each(vec.begin(), vec.end(), acc);
// acc.counter contains the sum of all elements of the vector

// Using a function pointer
std::for_each(vec.begin(), vec.end(), print); // prints all elements

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

نصائح أخرى

وانها تسمح فئة لتكون بمثابة وظيفة. لقد استخدمت في فئة تسجيل حيث يجب أن يكون دعوة وظيفة ولكن أردت فائدة إضافية من الطبقة.

وهكذا شيئا من هذا القبيل:

logger.log("Log this message");

ويتحول إلى ما يلي:

logger("Log this message");

وكثيرون قد أجبت أنه يجعل functor، دون أن يخبر سبب واحد كبير لماذا functor أفضل من وظيفة سهل القديمة.

والجواب هو أن functor يمكن أن يكون دولة. النظر في وظيفة التلخيص - أنه يحتاج للحفاظ على ما مجموعه تشغيل

class Sum
{
public:
    Sum() : m_total(0)
    {
    }
    void operator()(int value)
    {
        m_total += value;
    }
    int m_total;
};

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

وكما قال غيرها من الملصقات: [فونكتورس] لديها ميزة على وظائف مدنية لأنها يمكن أن يكون لها الدولة. هذه الحالة يمكن استخدام أكثر من التكرار واحد (على سبيل المثال لحساب مجموع كل العناصر في حاوية) أو عبر التكرار متعددة (على سبيل المثال للعثور على كافة العناصر في حاويات متعددة تلبية معايير معينة).

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

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

والمنفذون هم في الأساس مثل مؤشرات الدالة. وهي تهدف بشكل عام إلى أن copyable (مثل مؤشرات الدالة) والاستناد إليها في نفس الطريقة كما مؤشرات الدالة. والميزة الرئيسية هي أنه عندما يكون لديك الخوارزمية التي تعمل مع functor قالب، استدعاء دالة على المشغل () يمكن inlined. ومع ذلك، مؤشرات الدالة لا تزال صالحة [فونكتورس].

واستخدام مشغل () لتشكيل [فونكتورس] في C ++ يرتبط <أ href ل = "http://en.wikipedia.org/wiki/Functional_programming" يختلط = "نوفولو noreferrer"> الوظيفية نماذج البرمجة التي تجعل عادة استخدام مفهوم مماثل: <لأ href = "HTTP: // داخلي. wikipedia.org/wiki/Closure_(computer_science) "يختلط =" نوفولو noreferrer "> إغلاق .

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

T t;
t.write("Hello world");

ولأن T لديه شرط أن هناك دالة عضو يسمى الكتابة التي تقبل أي شيء castable ضمنا إلى CONST شار * (أو شار CONST بدلا []). الطبقة المراسل في هذا المثال لم يكن لديك ذلك، وذلك بعد T (معلمة قالب) من شأنه أن يكون مراسل تفشل في ترجمة.

ولكن، حتى ما أستطيع أن أرى هذا من شأنه أن يعمل مع أنواع مختلفة

T t;
t("Hello world");

وعلى الرغم من أنه لا يزال يتطلب صراحة على أن نوع T وهذا المشغل تعريف، لذلك لا يزال لدينا شرط على T. شخصيا، لا أعتقد أنها غريب جدا مع [فونكتورس] كما أنها تستخدم عادة ولكن أود أن أرى بدلا آليات أخرى لهذا السلوك. في لغات مثل C # هل يمكن أن يمر في مندوبا. أنا لست على دراية جدا مع مؤشرات دالة عضو في C ++ ولكن يمكنني أن أتصور أنك يمكن أن تحقق نفس السلوك هناك aswell.

وبخلاف السلوك السكر syntatic لا أرى حقا نقاط القوة في المشغل الحمولة الزائدة لأداء هذه المهام.

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

وأشار زميل في العمل آخر إلى أنه يمكن أن يكون وسيلة لإخفاء الأجسام functor وظائف. على سبيل المثال، ما يلي:

my_functor();

هل حقا:

my_functor.operator()();

هل يعني هذا:

my_functor(int n, float f){ ... };

ويمكن أن تستخدم لزيادة التحميل هذا أيضا؟

my_functor.operator()(int n, float f){ ... };

وفعلت وظائف أخرى بعمل جيد يصف كيف يعمل المشغل () وماذا يمكن أن يكون مفيدا.

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

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