cout перегружен, так что, когда вы даете ему char *, он будет печататься как указатель на строку стиля C. Таким образом, он печатает символы до тех пор, пока не ударит нулевой завершающий символ.
Если вы использовали printf вместо cout, вы увидите адрес. Вы также можете направить указатель на другой тип, скажем (void *), и вы также получите адрес.
Если метод не помечен как virtual
, он не сохраняется в виртуальной таблице. В этом случае деструктор не сохраняется в виртуальной таблице. Так что это нельзя назвать.
С текущим кодом, vtables будет выглядеть следующим образом:
vtable for Derived:
.quad 0
.quad typeinfo for Derived
.quad Base::f()
vtable for Base:
.quad 0
.quad typeinfo for Base
.quad Base::f()
См. Демо здесь
[1110 ] Если деструктор помеченvirtual
в Base
, vtables будет выглядеть следующим образом:
vtable for Derived:
.quad 0
.quad typeinfo for Derived
.quad Derived::~Derived() [complete object destructor]
.quad Derived::~Derived() [deleting destructor]
.quad Base::f()
vtable for Base:
.quad 0
.quad typeinfo for Base
.quad Base::~Base() [complete object destructor]
.quad Base::~Base() [deleting destructor]
.quad Base::f()
Не забывайте делать деструктор базового класса virtual
, если вы планируете выводить классы из него.
пометив его как виртуальный в базовом классе, сообщит компилятору, что он также хочет уничтожить производный объект, удаляя при этом базовый объект.
class Base
{
public:
Base() {}
virtual ~Base() { std::cout << "Base Destructed" << std::endl; }
virtual void f() {}
};
Но стоит отметить, что вы не ставите виртуальные перед функциями, которые вы не собираетесь переопределять. Потому что это связано с дополнительными затратами на обслуживание виртуальной таблицы.
https://www.crashhandler.com/2019/03/make-destructors-destroy-virtually.html Это моя запись в блоге на эту тему.