سؤال

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

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

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

-نيكولاس

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

المحلول

يمكنك كتابة شيء مثل:

class EncryptionFunction
{
public:
    virtual Foo Run(Bar input) = 0;
    virtual ~MyFunction() {}
};

class SomeSpecificEncryptionFunction : public EncryptionFunction
{
    // override the Run function
};

// ...

std::vector<EncryptionFunction*> functions;

// ...

functions[2]->Run(data);

يمكنك استخدام operator() بدلاً من Run كاسم الوظيفة، إذا كنت تفضل ذلك.

نصائح أخرى

ما هو الخطأ في مجموعة الوظائف؟

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

مثال (الكتابة من رأسي، قد لا يتم تجميعها):

struct FunctionPair {
   EncodeFunction encode;
   DecodeFunction decode;
};
FunctionPair g_Functions[] = {
   { MyEncode1, MyDecode1 },
   { MySuperEncode, MySuperDecode },
   { MyTurboEncode, MyTurboDecode },
};

ما هو "القبيح" أو "الذي يصعب الحفاظ عليه" في النهج أعلاه؟

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

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

ثم قم بإنشاء متجه للاستراتيجيات، واستخدم هذا بدلاً من قائمة الوظائف.

لكن بصراحة، لا أرى مشكلة في مصفوفة الوظائف؛يمكنك بسهولة إنشاء typedef لتسهيل القراءة.على نحو فعال، سوف ينتهي بك الأمر بنفس بنية الملف تمامًا عند استخدام نمط الإستراتيجية.

// functiontype.h
typedef bool (*forwardfunction)( double*, double* );

// f1.h
#include "functiontype.h"
bool f1( double*, double* );

// f1.c
#include "functiontype.h"
#include "f1.h"
bool f1( double* p1, double* p2 ) { return false; }


// functioncontainer.c    
#include "functiontype.h"
#include "f1.h"
#include "f2.h"
#include "f3.h"

forwardfunction my_functions[] = { f1, f2, f3 };
  • إعلان الوظيفة وتعريفاتها موجودة في ملفات منفصلة - وقت الترجمة مناسب.
  • توجد مجموعة الوظائف في ملف منفصل، ولها تبعية للإعلانات فقط

يمكنك إلقاء نظرة على مكتبة Boost.Signals.أعتقد أن لديه القدرة على استدعاء وظائفه المسجلة باستخدام فهرس.

جرب فئة Loki::Functor.مزيد من المعلومات في CodeProject.com

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

int Proto1( void );
int Proto2( void );
int Proto3( void );

int (*functinPointer[3])( void ) =
{
   Proto1,
   Proto2,
   Proto3
};

ثم يمكنك القيام بشيء مثل هذا:

int iFuncIdx = 0;
int iRetCode = functinPointer[iFuncIdx++]();

إذا نظرت في boost::signals مكتبة، سترى مثالًا جميلًا جدًا، وأنيقًا جدًا:
لنفترض أن لديك 4 وظائف مثل:

void print_sum(float x, float y)
{
  std::cout << "The sum is " << x+y << std::endl;
}

void print_product(float x, float y)
{
  std::cout << "The product is " << x*y << std::endl;
}

void print_difference(float x, float y)
{
  std::cout << "The difference is " << x-y << std::endl;
}

void print_quotient(float x, float y)
{
  std::cout << "The quotient is " << x/y << std::endl;
}

ثم إذا كنت تريد الاتصال بهم بطريقة أنيقة حاول:

boost::signal<void (float, float)> sig;

sig.connect(&print_sum);
sig.connect(&print_product);
sig.connect(&print_difference);
sig.connect(&print_quotient);

sig(5, 3);

والناتج هو:

The sum is 8
The product is 15
The difference is 2
The quotient is 1.66667
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top