#c
#c
Вопрос:
Я хотел бы знать, почему тип класса изменяется при использовании строки и виртуальной функции.
#include <iostream>
#include <typeinfo>
class Base {
public:
std::string str;
virtual void vvfunc() {};
};
class Derived : public Base {
public:
void vvfunc() {}
};
using namespace std;
int main() {
Derived* pd = new Derived;
Derived* pd2 = pd;
cout<<amp;pd<<endl;
cout<<amp;pd2<<endl;
cout << typeid( pd ).name() << endl;
cout << typeid( *pd ).name() << endl;
cout << typeid( pd2 ).name() << endl;
cout << typeid( *pd2 ).name() << endl;
delete pd;
cout << typeid( pd2 ).name() << endl;
cout << typeid( *pd2 ).name() << endl;
}
вывод
0x7ffeeaadd8f0
0x7ffeeaadd8d8
P7Derived
7Derived
P7Derived
7Derived
P7Derived
4Base
И когда я не использую «виртуальный», тогда я могу получить тот тип класса, который мне нужен.(или не используя строку в классе, что приводит к тому же результату)
#include <iostream>
#include <typeinfo>
class Base {
public:
std::string str;
void vvfunc() {};
};
class Derived : public Base {
public:
void vvfunc() {}
};
using namespace std;
int main() {
Derived* pd = new Derived;
Derived* pd2 = pd;
cout<<amp;pd<<endl;
cout<<amp;pd2<<endl;
cout << typeid( pd ).name() << endl;
cout << typeid( *pd ).name() << endl;
cout << typeid( pd2 ).name() << endl;
cout << typeid( *pd2 ).name() << endl;
delete pd;
cout << typeid( pd2 ).name() << endl;
cout << typeid( *pd2 ).name() << endl;
}
вывод
0x7ffeec60e790
0x7ffeec60e778
P7Derived
7Derived
P7Derived
7Derived
P7Derived
7Derived
Кто-нибудь может объяснить, почему это происходит?
Комментарии:
1. Поскольку
pd2
имеет то же значение,pd
что и , разыменованиеpd2
afterdelete pd;
имеет неопределенное поведение.2. Вы не можете разыменовывать указатель, если объект, на который он указывает, больше не существует. Вы понимаете, что оба
pd
pd2
указателя и указывают на один и тот же объект? Вы можете проверить, напечатав адрес этого объекта:amp;*pd
иamp;*pd2
(теперь вы печатаете адреса самих указателей, которые отличаются).3. Программа выдает ошибку сегментации, потому что вы удалили объект, а затем разыменовали его. Но я не получаю тот же результат, который вы получили в моем компиляторе g . Не могли бы вы, пожалуйста, изменить компилятор и перепроверить, совпадают ли выходные данные?
4. Я использовал clang (Apple LLVM версии 10.0.1 (clang-1001.0.46.4)). Спасибо всем вам за ответ на мой вопрос. И я понимаю, что последующий код
delete
неверен, и у моего компилятора было неправильное поведение.