è perché si sta tentando di convertire da int** to const int**
int ** v = new int * [10]; // v is int**
foo(v); //but foo takes const int**
int **
è: "un puntatore a un puntatore a un intero".
const int **
è: "un puntatore a un puntatore a un numero intero costante".
L'uso di const
è un contratto e non è possibile soddisfare questo contratto passando attraverso l'indirezione di due riferimenti.
dalla norma:
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?
quindi sarebbe possibile modificare const char
sempre, basta usare sopra procedura.
E anche:
char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char * const*ps = a; // no error!
bello citare dal link sottostante:
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
relative a questo è anche la conversione non valida Derived** → Base**
. Se fosse legale convertire Derived** → Base**
, il Base**
potrebbe essere sottoposto a dereferenziazione (ottenendo un valore Base*
) e Base * potrebbe essere indirizzato a un oggetto di una classe derivata diversa, che potrebbe causare seri problemi.Capire perché:
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
considerare:
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 = ⊂
*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
}
Sarebbe consentito se il prototipo di foo era: 'vuoto foo (int * const *)' – IronMensan
ottengo 'riferimento non definito a' foo (int * const *) 'quindi. – user1170330
Hai cambiato il tipo anche nella definizione di 'foo'? –