Conversion from int** to const int**

前端 未结 3 1096
逝去的感伤
逝去的感伤 2020-12-10 05:22

Why do I get in this code:

void foo ( const int ** );

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

    return 0;
}

this error:

3条回答
  •  一个人的身影
    2020-12-10 06:00

    it is because you are trying to convert from int** to const int**

    int ** v = new int * [10]; // v is int**
    foo(v); //but foo takes const int**
    
    • int ** is: "a pointer to a pointer to an integer".
    • const int ** is: "a pointer to a pointer to a constant integer".

    The use of const is a contract and you cannot meet this contract by going through the indirection of two references.

    From the standard:

    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?
    

    so it would be possible to modify const char always, just use procedure above.

    And also:

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

    nice cite from the link below:

    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

    related to this is also invalid conversion Derived** → Base**. If it were legal to convert Derived** → Base**, the Base** could be dereferenced (yielding a Base*), and the Base* could be made to point to an object of a different derived class, which could cause serious problems. See why:

    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

    consider:

    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(carPtrPtr);
      NuclearSubmarine  sub; NuclearSubmarine* subPtr = ⊂
      *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 
    }
    

提交回复
热议问题