سؤال

نعم, أنا أفهم الفرق بينهما.ما أريد أن أعرفه هو:لماذا تجاوز الأسلوب ؟ ما هو جيد في ذلك ؟ في حالة الحمل الزائد:الميزة الوحيدة هي أنك لم للتفكير في أسماء مختلفة على الوظائف ؟

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

المحلول

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

void print(Foo const& f) {
    // print a foo
}

void print(Bar const& bar) {
    // print a bar
}

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

void print(Foo & f, PrintAttributes b) { 
    /* ... */ 
}

void print(Foo & f, std::string const& header, bool printBold) {
    print(f, PrintAttributes(header, printBold));
}

وهذا يمكن أن تكون مريحة للالمتصل، وإذا كانت الخيارات التي تأخذ الزائدة غالبا ما تستخدم.

تجاوز هو شيء مختلف تماما. أنها لا تتنافس مع الحمولة الزائدة. وهذا يعني أنه إذا كان لديك وظيفة الظاهري في الفئة الأساسية، يمكنك كتابة وظيفة مع نفس التوقيع في فئة مشتقة. وظيفة في فئة مشتقة <م> يتجاوز وظيفة القاعدة. عينة:

struct base {
    virtual void print() { cout << "base!"; }
}

struct derived: base {
    virtual void print() { cout << "derived!"; }
}

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

void doit(base &b) {
    // and sometimes, we want to print it
    b.print();
}

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

نصائح أخرى

وهذا سيضيف بعض مزيد من الوضوح إلى الأفكار.

لك أكثرتحميل وظائف لثلاثة أسباب:

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

    void Log(std::string msg); // logs a message to standard out
    void Log(std::string msg, std::ofstream); // logs a message to a file
    
  2. لتوفير اثنين (أو أكثر) من الطرق لأداء نفس العمل.المفتعلة على سبيل المثال:

    void Plot(Point pt); // plots a point at (pt.x, pt.y)
    void Plot(int x, int y); // plots a point at (x, y)
    
  3. لتوفير القدرة على أداء العمل ما يعادل إعطاء اثنين (أو أكثر) من مختلف أنواع المدخلات.المفتعلة على سبيل المثال:

    wchar_t      ToUnicode(char c);
    std::wstring ToUnicode(std::string s);
    

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


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

وتجاوز مفيد عند يرث من فئة أساسية وترغب في تمديد أو تعديل وظائفه. حتى عندما يلقي الكائن كما الفئة الأساسية، فإنه يدعو وظيفة متجاوزة، وليس قاعدة واحدة.

والزائد ليس من الضروري، لكنه متأكد يجعل الحياة أسهل أو أكثر قابلية للقراءة في بعض الأحيان. يمكن القول أنه يمكن أن يزيد الأمر سوءا، ولكن هذا عندما لا ينبغي أن تستخدم. على سبيل المثال، هل يمكن أن يكون اثنين من المهام التي تؤدي نفس العملية، ولكن العمل على أنواع مختلفة من الأشياء. على سبيل المثال يجب أن يكون Divide(float, float) مختلفة من Divide(int, int)، ولكنها في الأساس نفس العملية. لن يمكنك بدلا من تذكر اسم واحد طريقة "تقسيم"، من أن نتذكر "DivideFloat"، "DivideInt"، "DivideIntByFloat"، وهلم جرا؟

الناس بالفعل تعريف كل من الحمولة الزائدة و تجاوز لذا لن تفصيلا.

ASAFE سأل:

الميزة الوحيدة [الحمولة الزائدة] هو لم يفكر في عدة أسماء الوظائف ؟

1.لا يجب أن نفكر في عدة أسماء

و هذا هو بالفعل ميزة الأقوياء ، أليس كذلك ؟

دعونا نقارن مع المعروف C وظائف API و خيالية C++ المتغيرات:

/* C */
double fabs(double d) ;
int abs(int i) ;

// C++ fictional variants
long double abs(long double d) ;
double abs(double d) ;
float abs(float f) ;
long abs(long i) ;
int abs(int i) ;

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

و كل ما هو/هي ان القيمة المطلقة من بعض العددية متغير...

عمل واحد يعني واحد فقط اسم الدالة.

لاحظ أنك لا تقتصر على تغيير نوع واحد paramter.أي شيء يمكن أن تتغير ، طالما أنه من المنطقي.

2.للمشغلين ، وهو إلزامي

دعونا نرى من المشغلين:

// C++
Integer operator + (const Integer & lhs, const Integer & rhs) ;
Real operator + (const Real & lhs, const Real & rhs) ;
Matrix operator + (const Matrix & lhs, const Matrix & rhs) ;
Complex operator + (const Complex & lhs, const Complex & rhs) ;

void doSomething()
{
   Integer i0 = 5, i1 = 10 ;
   Integer i2 = i0 + i1 ; // i2 == 15

   Real r0 = 5.5, r1 = 10.3 ;
   Real r2 = r0 + r1 ; // r2 = 15.8

   Matrix m0(1, 2, 3, 4), m1(10, 20, 30, 40) ;
   Matrix m2 = m0 + m1 ; // m2 == (11, 22, 33, 44)

   Complex c0(1, 5), c1(10, 50) ;
   Complex c2 = c0 + c1 ; // c2 == (11, 55)
}

في المثال أعلاه ، هل تريد تجنب استخدام أي شيء آخر من + المشغل.

لاحظ أن C الضمني عامل الحمولة الزائدة على المدمج في الأنواع (بما في ذلك C99 نوع معقد):

/* C */
void doSomething(void)
{
   char c = 32 ;
   short s = 54 ;
   c + s ; /* == C++ operator + (char, short) */
   c + c ; /* == C++ operator + (char, char) */
}

حتى في غير وجوه لغات, هذا إثقال شيء يستخدم.

3.عن الأشياء ، وهو إلزامي

دعونا نرى استخدام كائن طرق أساسية:لها منشئات:

class MyString
{
   public :
      MyString(char character) ;
      MyString(int number) ;
      MyString(const char * c_style_string) ;
      MyString(const MyString * mySring) ;
      // etc.
} ;

بعض يمكن أن نعتبر هذا مثل وظيفة الحمولة الزائدة ، ولكن في الواقع ، هو أكثر مماثلة إلى عامل الحمولة الزائدة:

void doSomething()
{
   MyString a('h') ;                  // a == "h" ;
   MyString b(25) ;                   // b == "25" ;
   MyString c("Hello World") ;        // c == "Hello World" ;
   MyString d(c) ;                    // d == "Hello World" ;
}

الخلاصة:الحمولة الزائدة هو بارد

في C ، عند إعطاء اسم وظيفة معلمات implicitely جزء من التوقيع في الدعوة.إذا كان لديك "مزدوجة fabs مزدوجة(د)" ، ثم حين توقيع fabs المترجم هو غير مزخرف "fabs" ، وهو ما يعني أن لك يجب أن نعلم أن الأمر يتطلب فقط الزوجي.

في C++, اسم الوظيفة لا يعني التوقيع القسري.التوقيع في الدعوة اسمها ومعالمها.وهكذا, إذا كنت أكتب abs(-24), المترجم سوف نعرف ما الحمولة الزائدة من abs يجب أن ندعو وأنت عند كتابة ذلك ، تجد أنه أكثر الطبيعية:كنت تريد القيمة المطلقة -24.

على أية حال أي شخص مشفرة إلى حد ما في أي لغة مع مشغلي بالفعل يستخدم الحمولة الزائدة ، سواء كان C أو العددية الأساسية مشغلي جافا سلسلة سلسلة, C# المندوبين ، الخ..لماذا ؟ لأنه أكثر طبيعية.

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

والمثال كتاب من الدرجة الحيوانية مع طريقة الكلام (). تجاوزات فرعية الكلب تتحدث () ل"النباح" حين تتحدث تجاوزات القط فرعية () ل"مواء".

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

وفي حين قد لا تكون كتابة القوالب حتى الآن، وكنت شبه المؤكد باستخدام بعض منهم. تيارات هي قوالب، وهكذا هي ناقلات. دون الحمولة الزائدة، وبالتالي دون القوالب، وكنت بحاجة إلى استدعاء يونيكود تيارات شيئا مختلفا من تيارات ASCII، وكنت قد لاستخدام المصفوفات والمؤشرات بدلا من ناقلات.

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