سؤال

وأنا لا يمكن العثور على الكثير من المعلومات عن const_cast. المعلومات الوحيدة التي يمكنني أن تجد (على تجاوز المكدس) هي:

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

ويستخدم const_cast<>() إضافة / إزالة CONST (نيس) (أو المتقلبة التي غمرت) متغير.

وهذا يجعلني عصبيا. يمكن استخدام السلوك سبب const_cast غير متوقع؟ إذا كان الأمر كذلك، ما هي؟

وبدلا من ذلك، عندما هل هو بخير لاستخدام const_cast؟

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

المحلول

وconst_cast آمنة فقط إذا كنت يلقي المتغير الذي كان في الأصل غير const. على سبيل المثال، إذا كان لديك دالة التي تأخذ معلمة من const char *، وأنت تمر في char * للتعديل، انها آمنة لconst_cast تلك المعلمة مرة أخرى إلى char * وتعديله. ومع ذلك، إذا كان المتغير الأصلي في الواقع const، ثم استخدام const_cast سوف يؤدي إلى سلوك غير معرف.

void func(const char *param, size_t sz, bool modify)
{
    if(modify)
        strncpy(const_cast<char *>(param), sz, "new string");
    printf("param: %s\n", param);
}

...

char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true);  // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true);  // UNDEFINED BEHAVIOR

نصائح أخرى

وأستطيع أن أفكر في حالتين حيث const_cast هي آمنة ومفيدة (قد تكون هناك حالات صالحة أخرى).

واحد هو عندما يكون لديك CONST المثال، إشارة، أو المؤشر، وتريد تمرير مؤشر أو إشارة إلى API غير-CONST الصحيح، ولكن ان كنت على يقين لن يقوموا بتعديل الكائن. يمكنك const_cast المؤشر وتمريرها إلى API، واثقين أنه لن يغير أي شيء في الواقع. على سبيل المثال:

void log(char* text);   // Won't change text -- just const-incorrect

void my_func(const std::string& message)
{
    log(const_cast<char*>(&message.c_str()));
}

ووالآخر هو إذا كنت تستخدم مترجم القديمة التي لا تنفذ "قابلة للتغيير، وكنت ترغب في إنشاء فئة غير CONST منطقيا ولكن ليس CONST أحادي المعامل. يمكنك const_cast 'هذا' داخل أسلوب CONST وتعديل أعضاء صفك.

class MyClass
{
    char cached_data[10000]; // should be mutable
    bool cache_dirty;        // should also be mutable

  public:

    char getData(int index) const
    {
        if (cache_dirty)
        {
          MyClass* thisptr = const_cast<MyClass*>(this);
          update_cache(thisptr->cached_data);
        }
        return cached_data[index];
    }
};

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

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

إذا يلقي بعيدا constness ل   الكائن الذي كان صراحة   أعلن وCONST، ومحاولة ل   تعديله، فإن النتائج تكون غير محددة.

     

ولكن، إذا كنت يلقي بعيدا   constness من كائن له لا   تم الإعلان صراحة CONST، ل   يمكن تعديله بأمان.

وماذا يقول آدم. مثال آخر حيث const_cast يمكن أن تكون مفيدة:

struct sample {
    T& getT() { 
        return const_cast<T&>(static_cast<const sample*>(this)->getT()); 
    }

    const T& getT() const { 
       /* possibly much code here */
       return t; 
    }

    T t;
};

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

والجواب باختصار هو لا، انها ليست آمنة.

والجواب طويلة هو أنه إذا كنت تعرف ما يكفي لاستخدامه، ومن ثم ينبغي أن تكون آمنة.

وعندما كنت الصب، ما تقوله في الأساس هو، "أعرف شيئا المترجم لا يعرف". في حالة const_cast، ما تقوله هو، "على الرغم من أن هذا الأسلوب يأخذ في اشارة غير CONST أو المؤشر، وأنا أعلم أنه لن يغير المعلمة أمرر عليه".

وحتى إذا كنت لا تعرف فعلا ما كنت تدعي أن نعرف في استخدام المدلى بها، ثم لا بأس في استخدامه.

وأنت تدمير أي فرصة في موضوع السلامة، إذا قمت بتشغيل تعديل الأشياء التي المترجم يعتقد ان CONST.

#include <iostream>
using namespace std;

void f(int* p) {
  cout << *p << endl;
}

int main(void) {
  const int a = 10;
  const int* b = &a;

  // Function f() expects int*, not const int*
  //   f(b);
  int* c = const_cast<int*>(b);
  f(c);

  // Lvalue is const
  //  *b = 20;

  // Undefined behavior
  //  *c = 30;

  int a1 = 40;
  const int* b1 = &a1;
  int* c1 = const_cast<int*>(b1);

  // Integer a1, the object referred to by c1, has
  // not been declared const
  *c1 = 50;

  return 0;
}

المصدر: <لأ href = "http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp؟topic=٪2Fcom.ibm.xlcpp8a.doc٪2Flanguage٪2Fref٪2Fkeyword_const_cast.htm "يختلط =" نوفولو "> http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp؟topic=٪2Fcom.ibm.xlcpp8a.doc٪2Flanguage٪2Fref٪2Fkeyword_const_cast.htm

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