سؤال

ونحن نعلم جميعا أن تتمكن من التحميل الزائد وظيفة وفقا لمعايير:

int mul(int i, int j) { return i*j; }
std::string mul(char c, int n) { return std::string(n, c); } 

هل أنت الزائد وظيفة وفقا لقيمة العودة؟ تعريف دالة ترجع الأمور مختلفة وفقا لكيفية استخدام قيمة الإرجاع:

int n = mul(6, 3); // n = 18
std::string s = mul(6, 3); // s = "666"
// Note that both invocations take the exact same parameters (same types)

ويمكنك أن تفترض المعلمة الأولى ما بين 0-9، لا حاجة للتحقق من إدخال أو لديك أي معالجة الأخطاء.

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

المحلول

class mul
{
public:
    mul(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

وليس ذلك أود أن استخدام ذلك.

نصائح أخرى

وعليك أن نقول للمترجم أي إصدار للاستخدام. في C ++، يمكنك أن تفعل ذلك ثلاث طرق.

صراحة يفرق المكالمات عن طريق كتابة

ويمكنك خداع بعض الشيء لأنك أرسلت عددا صحيحا إلى وظيفة تنتظر شار، وإرسالها بشكل خاطئ عدد ستة عندما تكون القيمة شار من "6" ليست 6 ولكن 54 (في ASCII):

std::string mul(char c, int n) { return std::string(n, c); }

std::string s = mul(6, 3); // s = "666"

وقال إن الحل الصحيح يكون، بطبيعة الحال،

std::string s = mul(static_cast<char>(54), 3); // s = "666"

وكانت هذه الجدير بالذكر، أعتقد، حتى لو كنت لا تريد الحل.

صراحة التفريق بين دعوات مؤشر وهمية

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

int mul(int *, int i, int j) { return i*j; }
std::string mul(std::string *, char c, int n) { return std::string(n, c); }

والتي يمكن استخدامها مع رمز:

int n = mul((int *) NULL, 6, 3); // n = 18
std::string s = mul((std::string *) NULL, 54, 3); // s = "666"

صراحة التفريق بين دعوات النموذجيه قيمة الإرجاع

ومع هذا الحل، ونحن خلق وظيفة "زائف" مع التعليمات البرمجية التي لن تجميع إذا مثيل:

template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

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

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

template<>
std::string mul<std::string>(int i, int j)
{
   return std::string(j, static_cast<char>(i)) ;
}

وهكذا، فإن البرمجية التالية تجميع:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>(54, 3); // s = "666"

ولكن هذا واحد لن:

short n2 = mul<short>(6, 3); // error: assignment of read-only variable ‘k’

صراحة التفريق بين دعوات النموذجيه قيمة الإرجاع، 2

<اقتباس فقرة>   <اقتباس فقرة>     

ومهلا، أنت لغش، أيضا!

  

والحق، وفعلت استخدام نفس المعلمات لوظائف "زائد" اثنين. ولكنك لم تبدأ الغش (انظر أعلاه) ...

^ _ ^

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

// For "int, int" calls
template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

// For "char, int" calls
template<typename T>
T mul(char i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
std::string mul<std::string>(char i, int j)
{
   return std::string(j, (char) i) ;
}

وسوف تستخدم هذا الرمز على هذا النحو:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>('6', 3); // s = "666"

والسطر التالي:

short n2 = mul<short>(6, 3); // n = 18

هل لا يزال غير ترجمة.

الخاتمة

وأنا أحب C ++ ...

: - p

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

class StringOrInt
{
public:
    StringOrInt(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

StringOrInt mul(int p1, int p2)
{
    return StringOrInt(p1, p2);
}

وهذا يتيح لك أن تفعل أشياء مثل التي تمر mul بوصفها وظيفة في خوارزميات الأمراض المنقولة جنسيا:

int main(int argc, char* argv[])
{
    vector<int> x;
    x.push_back(3);
    x.push_back(4);
    x.push_back(5);
    x.push_back(6);

    vector<int> intDest(x.size());
    transform(x.begin(), x.end(), intDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 15 20 25 30
    for (vector<int>::const_iterator i = intDest.begin(); i != intDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    vector<string> stringDest(x.size());
    transform(x.begin(), x.end(), stringDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 555 5555 55555 555555
    for (vector<string>::const_iterator i = stringDest.begin(); i != stringDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    return 0;
}

لا.

وأنت لا يمكن أن تفرط من قيمة الإرجاع لأن المتصل يمكن أن تفعل أي شيء (أو لا شيء) معها. النظر فيما يلي:

وmul(1, 2);

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

استخدم التحويل الضمني في ما بين الفئة.

class BadIdea
{
  public:
    operator string() { return "silly"; }
    operator int() { return 15; }
};

BadIdea mul(int, int)

ويمكنك الحصول على هذه الفكرة، فكرة رهيبة بالرغم من ذلك.

واسمحوا MUL تكون فئة، MUL (س، ص) المنشئ الخاص به، والزائد بعض مشغلي الصب.

وأنت لا يمكن أن تفرط وظيفة على أساس قيمة الإرجاع فقط.

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

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

وهممم، و كود المادة المشروع يبدو أن تفعل ما كنت بعد. يجب أن يكون السحر؛)

وقصيرة وبسيطة، والجواب هو لا. في ++ C المتطلبات هي:

1: اسم من الوظائف يجب أن تكون نفس
2: مجموعة من الحجج يجب أن تختلف
* نوع الإرجاع يمكن أن تكون هي نفسها أو مختلفة

//This is not valid
    int foo();
    float foo();

    typedef int Int;

    int foo(int j);
    int foo(Int j);

//Valid:
   int foo(int j);
   char* foo(char * s);
   int foo(int j, int k);
   float foo(int j, float k);
   float foo(float j, float k);

وبقدر ما أعرف، لا يمكنك (شفقة كبيرة، على الرغم من ...). كحل مؤقت، يمكنك تعريف المعلمة 'خارج' بدلا من ذلك، والزائد ان واحد.

وليس في C ++. ما كنت أحصل في المثال أعلاه ستكون القيمة التي تم إرجاعها وهو يلقي الباحث إلى شيء string يمكن أن نفهم، وعلى الأرجح char. التي ستكون ASCII 18 أو "جهاز التحكم 2".

ويمكنك استخدام الحل functor أعلاه. لا يدعم C ++ هذا لوظائف باستثناء CONST. يمكنك الزائد على أساس CONST.

هل يمكن استخدام قالب، ولكن بعد ذلك عليك أن تحدد المعلمة القالب عند إجراء المكالمة.

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

وهكذا stringnamespace :: MUL وintnamespace :: MUL. ربما ليست حقا ما كنت طالبا، ولكن يبدو أن الطريقة الوحيدة للقيام بذلك.

هل يمكن أن تفعل شيئا من هذا القبيل

template<typename T>
T mul(int i,int j){
    return i * j;
}

template<>
std::string mul(int i,int j){
    return std::string(j,i);
}

وبعد ذلك يطلق عليه مثل هذا:

int x = mul<int>(2,3);
std::string s = mul<std::string>(2,3);

وليس هناك وسيلة لإثقال على قيمة المقابل.

وOK لك العباقرة؛) هذه هي الطريقة التي كنت تفعل ذلك مثل الموالية

.

class mul
{
 int m_i,m_j;
public:
 mull(int i,int j):m_i(i),m_j(j){}
 template
 operator R() 
 {
  return (R)m_i * m_j;
 }
};

واستخدام مثل


double d = mul(1,2);
long l = mul(1,2);

وليس غبي <>

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