наследование — почему я могу изменять переменную const через классы, а не в виде простого кода. Переполнение стека

Когда я пишу этот фрагмент кода, после изменения значения переменной const i через указатель я получаю значение i как 10, но когда я печатаю * ptr, я получаю 110.

const int i = 10;
int *ptr = const_cast<int *>(&i);
*ptr = *ptr + 100;
cout << "i:     " << i << "\t*ptr:      " << *ptr << endl;

Я получаю выходные данные i: 10 и * ptr: 110.

И в этом случае у меня есть константная переменная x в качестве переменной-члена класса Base. И с помощью функции show () я могу изменить значение переменной const x, т.е. когда я печатаю x и * ptr, я получаю измененное значение в обоих.

class Base
{
public:
const int x;
Base(int i) : x(i) {}
virtual void show()
{
int *ptr = const_cast<int *>(&x);
int *ptr = const_cast<int *>(&x);
cout << "In Base show:\n";
cout << "Address of x   :       " << &x << endl;
cout << "Address in ptr :       " << ptr << endl;
cout << "value in x     :       " << x << endl;
cout << "value in ptr   :       " << *ptr << endl;
*ptr = *ptr + 10;
cout << "After modifying        " << endl;
cout << "value in x     :       " << x << endl;
cout << "value in ptr   :       " << *ptr << endl;
}
};

class Derived : public Base
{
public:
Derived(int i) : Base(i){}
virtual void show()
{
int *ptr = const_cast<int *>(&x);
cout << "In Derived show:\n";
cout << "Address of x   :       " << &x << endl;
cout << "Address in ptr :       " << ptr << endl;
cout << "value in x     :       " << x << endl;
cout << "value in ptr   :       " << *ptr << endl;
*ptr = *ptr + 10;
cout << "After modifying        " << endl;
cout << "value in x     :       " << x << endl;
cout << "value in ptr   :       " << *ptr << endl;
}
};
int main()
{
Base bobj(5),*bp;
Derived dobj(20), *dptr;
bp = &bobj;
bp->show();
bp = &dobj;
bp->show();
return 0;
}The output which I am getting is this
In Base show:
Address of x    :   0x7fff82697588
Address in ptr  :   0x7fff82697588
value in x          :   5
value in ptr    :   5
After modifying
value in x          :   15
value in ptr    :   15

In Derived show:
Address of x        :       0x7fff82697578
Address in ptr      :   0x7fff82697578
value in x          :       20
value in ptr        :       20
After modifying
value in x          :       30
value in ptr        :       30

Кто-нибудь может помочь.

0

Решение

Причина в том, что ваш компилятор указал значение i в код при компиляции этой строки:

cout << "i: " << i << "\t*ptr: " << *ptr << endl;

Так как i это const переменной, компилятор оптимизировал код, заменив i в приведенной выше строке с 10, Если мы посмотрим на сгенерированную сборку (я использую VS2010):

002314F2  mov         ecx,dword ptr [ptr]  // ptr is being pushed here (110)
002314F5  mov         edx,dword ptr [ecx]
002314F7  push        edx
002314F8  push        offset string "\t*ptr:      " (23783Ch)
002314FD  mov         ebx,esp
002314FF  push        0Ah  //  0Ah is being pushed here (A is hex for 10)
00231501  push        offset string "i:     " (237830h)

Произошло то, что вы изменили константу в памяти, но сгенерированная сборка фактически не использует адрес памяти — она ​​просто выводит «10» независимо от того, что находится в памяти.

Как сказал Kerrek, это неопределенное поведение, поэтому другие компиляторы могут сделать что-то совершенно другое.

В общем, это плохая идея const_cast за редким исключением.

1

Другие решения

Ваш код просто имеет неопределенное поведение: вы не должны изменять постоянный объект, а ваш const_cast позволяет нарушать это (вот почему это в основном никогда хорошая идея использовать const_castс очень редкими и очень редкими исключениями). Поэтому нет смысла расспрашивать о причинах и причинах того, как ваш код ломается. Но если вы должны знать, константные интегральные выражения часто складываются по значению прямо в местах, к которым они относятся, что похоже на то, что происходит в вашем случае.

3

По вопросам рекламы [email protected]