Как использовать указатель Foo* * для const Foo** в C++
Я
class Fred
{
public:
void inspect() const {};
void modify(){};
};
int main()
{
const Fred x = Fred();
Fred* p1;
const Fred** q1 = reinterpret_cast<const Fred**>(&p1);
*q1 = &x;
p1->inspect();
p1->modify();
}
как было бы возможно сделать const Fred* * q1 = &p1 через кастинг указателей?
(Я только что читал, что это возможно)
Спасибо за ваши ответы. В const_cast действительно работает для объектов
#include <iostream>
#include <stdio.h>
using namespace std;
class Fred
{
int a;
public:
Fred(){};
Fred(int a_input)
{
a = a_input;
};
void inspect() const
{
cout << "Inspect called"<< endl;
cout << "Value is ";
cout << a << endl;
};
void modify()
{
cout << "Modify called" << endl;
a++;
};
};
int main()
{
const Fred x = Fred(7);
const Fred* q1 = &x;
Fred* p1 = const_cast<Fred*>(q1);
p1->inspect();
p1->modify();
p1->inspect();
x.inspect();
*p1 = Fred(10);
p1->inspect();
}
дает
Inspect called
Value is 7
Modify called
Inspect called
Value is 8
Inspect called
Value is 8
Inspect called
Value is 10
Inspect called
Value is 10
однако, для предопределенных типов он не работает:
int main()
{
const double a1 = 1.2;
const double* b1 = &a1;
cout << "a1 is " << (*b1) << endl;
cout << "b1 is " << b1 << endl;
double* c1 = const_cast<double*>(&a1);
cout << "b1 is " << b1 << endl;
cout << "c1 is " << c1 << endl;
double* d1 = static_cast<double*>(static_cast<void*>(c1));
cout << "d1 is " << d1 << endl;
cout<< "*d1 is " << *d1 << endl;
*d1=7.3;
cout<< "*d1 is " << *d1 << endl;
cout<< "*d1 address is "<< d1 << endl;
cout << "a1 is " << a1 << endl;
cout << "a1 address is" << &a1 << endl;
cout<< "*d1 is " << *d1 << endl;
cout<< "*d1 address is "<< d1 << endl;
double f1=a1;
printf("f1 is %f n", f1);
}
результат:
a1 is 1.2
b1 is 0xffbff208
b1 is 0xffbff208
c1 is 0xffbff208
d1 is 0xffbff208
*d1 is 1.2
*d1 is 7.3
*d1 address is 0xffbff208
a1 is 1.2
a1 address is0xffbff208
*d1 is 7.3
*d1 address is 0xffbff208
f1 is 1.200000
видимо компилятор G++ оптимизирует так, что он заменяет a1 на 1.2 всякий раз, когда находит его, поэтому, даже если его значение в стеке изменилось, ему все равно.
(в моем случае у меня были проблемы с прямым чтением *b1, *c1, поэтому мне пришлось сделать двойной статический бросок - переинтерпретировать бросок не работал).
есть ли способ действительно изменить a1, компилируя "нормально", поэтому не компилируя без оптимизации (поэтому я обгоняю эффект оптимизации)?
6 ответов
Это не очень хорошая идея, потому что это нарушает безопасность типов. Позвольте мне объяснить, почему:
Fred* pFred;
const Fred** ppFred = const_cast<const Fred**>(&p);
*ppFred = new const Fred; // Now pFred points to a const Fred
pFred->some_evil_mutating_method(); // can do, since type of *pFred is non-const!
почему бы вам просто не сделать:?
const Fred** q1;
*q1 = p1;
или вы хотите устранить нарушение константы без const_cast? -- нет, сэр, не можете.--2-->
вы не должны делать это. Тот факт, что вы не можете легко выполнить преобразование, потому что он нарушает постоянную корректность (и ваш код выполняет ее). Используя рекомендации выше, ваш код будет компилироваться и вызовет метод мутации для постоянного объекта (последняя строка кода).
Это не рекомендуется и в некоторых редких случаях может даже убить ваше приложение (постоянный глобальный объект может храниться на странице памяти только для чтения) или оставить его нестабильной ситуацией (вы меняете внутреннее состояние объекта путем изменения через постоянную ссылку на внутренний элемент-член, нарушая инварианты объекта).
о своей проблеме: C++ FAQ Lite [18.17]
вам не нужно делать никакого кастинга для const Fred** q1 = &p1
Как неконстантную Fred**
может быть непосредственно назначена const Fred** q1
в своем заявлении.