2013-05-05 10 views
6

मैं इस कोड में क्यों मिलता है:रूपांतरण ** const करने के लिए int **

void foo (const int **); 

int main() { 
    int ** v = new int * [10]; 
    foo(v); 

    return 0; 
} 

इस त्रुटि:

invalid conversion from ‘int**’ to ‘const int**’ [-fpermissive]| 

मैंने सोचा कि यह गैर स्थिरांक से कन्वर्ट करने के लिए संभव हो जाएगा कॉन्स करने के लिए।

+2

यह अनुमति दी जाएगी अगर foo के प्रोटोटाइप था: 'शून्य foo (int * स्थिरांक *)' – IronMensan

+0

मैं यह मध्यवर्ती स्तर पर जोड़ने स्थिरांक को छोड़ देते हैं की अनुमति दी गई, तो आप की तरह कुछ करने के लिए सक्षम हो जाएगा 'foo (int * const *) 'के लिए अपरिभाषित संदर्भ। – user1170330

+0

क्या आपने 'foo'' की परिभाषा में भी प्रकार बदल दिया था? –

उत्तर

14

यह इसलिए है क्योंकि आप कन्वर्ट करने के लिए int** to const int**

int ** v = new int * [10]; // v is int** 
foo(v); //but foo takes const int** 
  • int ** से है कोशिश कर रहे हैं: "एक पूर्णांक के लिए सूचक के लिए सूचक"।
  • const int ** है: "एक पॉइंटर को एक स्थिर पूर्णांक के लिए सूचक"।

const का उपयोग एक अनुबंध है और आप दो संदर्भों के संकेत के माध्यम से इस अनुबंध को पूरा नहीं कर सकते हैं।

मानक से:

const char c = 'c'; 
char* pc; 
const char** pcc = &pc; // not allowed (thankfully!) 
       ^^^ here the bundit is hidden under const: "I will not modify" 
*pcc = &c;    // *pcc is "pointer to const" right? so this is allowed... 
*pc = 'C';    // would allow to modify a const object, *pc is char right? 

तो यह const charहमेशा संशोधित करने के लिए संभव हो जाएगा, बस प्रक्रिया ऊपर का उपयोग करें।

और यह भी:

char *s1 = 0; 
const char *s2 = s1; // OK... 
char *a[MAX]; // aka char ** 
const char * const*ps = a; // no error! 

अच्छा नीचे दिए गए लिंक से अदालत में तलब:

By way of analogy, if you hide a criminal under a lawful disguise, he can then exploit the trust given to that disguise. That's bad.

http://www.parashift.com/c++-faq-lite/constptrptr-conversion.html

इस से संबंधित भी अवैध रूपांतरण Derived** → Base** है। यदि Derived** → Base** को परिवर्तित करना कानूनी था, तो Base** को संदर्भित किया जा सकता था (Base* प्रदान करना), और आधार * को एक अलग व्युत्पन्न वर्ग की वस्तु को इंगित करने के लिए बनाया जा सकता है, जिससे गंभीर समस्याएं हो सकती हैं।देखें क्यों:

class Vehicle { 
public: 
    virtual ~Vehicle() { } 
    virtual void startEngine() = 0; 
}; 

class Car : public Vehicle { 
public: 
    virtual void startEngine(); 
    virtual void openGasCap(); 
}; 

class NuclearSubmarine : public Vehicle { 
public: 
    virtual void startEngine(); 
    virtual void fireNuclearMissle(); 
}; 

int main() 
{ 
    Car car; 
    Car* carPtr = &car; 
    Car** carPtrPtr = &carPtr; 
    Vehicle** vehiclePtrPtr = carPtrPtr; // This is an error in C++ 
    NuclearSubmarine sub; 
    NuclearSubmarine* subPtr = ⊂ 
    *vehiclePtrPtr = subPtr; 
    // This last line would have caused carPtr to point to sub ! 
    carPtr->openGasCap(); // This might call fireNuclearMissle()! 
    ... 
} 

http://www.parashift.com/c++-faq-lite/derivedptrptr-to-baseptrptr.html

पर विचार करें:

class Vehicle { 
public: 
    virtual ~Vehicle() { } 
    virtual void startEngine() = 0; 
}; 
class Car : public Vehicle { 
public: 
    virtual void startEngine(){printf("Car engine brummm\n");} 
    virtual void openGasCap(){printf("Car: open gas cap\n");} 
    virtual void openGasCap2(){printf("Car: open gas cap2\n");} 
     virtual void openGasCap3(){printf("Car: open gas cap3\n");} 
      virtual void openGasCap4(){printf("Car: open gas cap4\n");} 
}; 
class NuclearSubmarine : public Vehicle { 
public: 
    int i; 
    virtual void startEngine(){printf("Nuclear submarine engine brummm\n");} 
    virtual void fireNuclearMissle3(){printf("Nuclear submarine: fire the missle3!\n");} 
    virtual void fireNuclearMissle(){printf("Nuclear submarine: fire the missle!\n");} 
    virtual void fireNuclearMissle2(){printf("Nuclear submarine: fire the missle2!\n");} 
}; 
int main(){ 
    Car car; Car* carPtr = &car; 
    Car** carPtrPtr = &carPtr; 
    //Vehicle** vehiclePtrPtr = carPtrPtr; // This is an error in C++, But: 
    Vehicle** vehiclePtrPtr = reinterpret_cast<Vehicle**>(carPtrPtr); 
    NuclearSubmarine sub; NuclearSubmarine* subPtr = &sub; 
    *vehiclePtrPtr = subPtr; // carPtr points to sub ! 
    carPtr->openGasCap(); // Nuclear submarine: fire the missle3! 
    carPtr->openGasCap2(); // Nuclear submarine: fire the missle! 
    carPtr->openGasCap3(); // Nuclear submarine: fire the missle2! 
    //carPtr->openGasCap4(); // SEG FAULT 
} 
2

आपको पॉइंटर्स के लिए सी ++ के भ्रमित पार्सिंग नियमों द्वारा यहां गुमराह किया जा रहा है। यह इस तरह से को देखने के लिए स्पष्ट हो सकता है:

typedef const int * ptr_to_const_int; 
void foo(ptr_to_const_int *); 
int main() { 
    int ** v = new int * [10]; 
    foo(v); 

    return 0; 
} 

क्या foo() के पैरामीटर सूची वादा करता है कि आप इसे एक (सूचक करने वाली लगातार बात) के सूचक के गुजर जाने वाली राशि है। लेकिन नया int * [10] का अर्थ है "पॉइंटर टू (पॉइंटर-टू-नॉन-निरंतर-चीज़)"।

तो अगर foo इस तरह परिभाषित किया गया:

foo(const int **p) 
{ 
    (*p); //<-- this is actually of type const int * 
} 

जबकि मुझे लगता है कि आप उम्मीद कर रहे हैं कि

foo(const int **p) 
{ 
    (*p); //<-- you're expecting this to be of type int * 
    p = 0; //<-- and this to throw a compiler error because p is const 
} 

लेकिन यह पी है कि आप लगातार होने की घोषणा कर रहे नहीं है, यह बात है यह इंगित करता है।

वैसे भी इस मामले में टाइपिफ़ का उपयोग करें और सब कुछ स्पष्ट और पठनीय होगा।

5

आप केवल स्थिरांक योग्यता समान सूचक प्रकार के बीच एक रूपांतरण में सभी स्तरों पर सीवी में पहली अंतर से जोड़ सकते हैं अगर आप स्थिरांक जोड़ने योग्यता और ऊपर।

तो, आप int** से int const* const* को परिवर्तित कर सकते हैं, लेकिन int const* * पर नहीं।

const int c = 29; 
int *pi; 
const int** ppci = &pi; // only adding const, right 
*ppci = &c; 
*pi = 0; // changing c ?! but no const_cast in sight 
संबंधित मुद्दे