سؤال

النظر في المقتطف التالي:

void Foo()
{
  // ...
}

void Bar()
{
  return Foo();
}

ما هو السبب المشروع لاستخدام ما سبق في C ++ بدلاً من النهج الأكثر شيوعًا:

void Foo()
{
  // ...
}

void Bar()
{
  Foo();

  // no more expressions -- i.e., implicit return here
}
هل كانت مفيدة؟

المحلول

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

#include <iostream>

template <typename T>
T retval() {
    return T();
}

template <>
void retval() {
    return;
}

template <>
int retval() {
    return 23;
}

template <typename T>
T do_something() {
    std::cout << "doing something\n";
}

template <typename T>
T do_something_and_return() {
    do_something<T>();
    return retval<T>();
}

int main() {
    std::cout << do_something_and_return<int>() << "\n";
    std::cout << do_something_and_return<void*>() << "\n";
    do_something_and_return<void>();
}

لاحظ ذلك فقط main يجب أن تتعامل مع حقيقة أنه في void حالة لا يوجد شيء للعودة من retval . الوظيفة الوسيطة do_something_and_return عام.

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

نصائح أخرى

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

يمكنك استخدامه في التعليمات البرمجية العامة ، حيث تكون قيمة إرجاع FOO () غير معروفة أو تخضع للتغيير. انصح:

template<typename Foo, typename T> T Bar(Foo f) {
    return f();
}

في هذه الحالة ، يكون الشريط صالحًا للفراغ ، ولكنه صالح أيضًا في حالة تغيير نوع الإرجاع. ومع ذلك ، إذا كان يطلق عليه فقط f ، فإن هذا الرمز سوف ينهار إذا كان t غير void. باستخدام العودة f () ؛ يضمن بناء الجملة الحفاظ على قيمة الإرجاع لـ FOO () إذا كان هناك واحد ، ويسمح بالفراغ ().

بالإضافة إلى ذلك ، فإن العودة بشكل صريح هي عادة جيدة للدخول.

قوالب:

template <typename T, typename R>
R some_kind_of_wrapper(R (*func)(T), T t)
{
   /* Do something interesting to t */
   return func(t);
}

int func1(int i) { /* ... */ return i; }

void func2(const std::string& str) { /* ... */ }

int main()
{
   int i = some_kind_of_wrapper(&func1, 42);

   some_kind_of_wrapper(&func2, "Hello, World!");

   return 0;
}

دون أن تكون قادرًا على إعادة الفراغ ، return func(t) في القالب لن يعمل عندما طُلب منه الالتفاف func2.

السبب الوحيد الذي يمكنني التفكير فيه هو إذا كان لديك قائمة طويلة من return Foo(); عبارات في مفتاح وأراد جعلها أكثر إحكاما.

والسبب هو إرجاع الذاكرة مثل Math.h يعود دائمًا. Math.h ليس لديه فراغ ولا حجج فارغة. هناك العديد من المواقف العملية التي تحتاج فيها إلى الذاكرة.

يمكن أن تكون حالة حيث Foo() أعاد في الأصل قيمة ، ولكن تم تغييره لاحقًا إلى void, والشخص الذي قام بتحديثه لم يفكر بوضوح شديد.

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