наследование c ++ - PullRequest
       29

наследование c ++

3 голосов
/ 01 апреля 2011

Я играл с некоторыми фьючерсами на c ++ и столкнулся с чем-то, что меня заинтриговало.

class Base
{
       public:
          Base(){ cout<<"C: Base"<<endl;}
          ~Base(){ cout<<"D : Base"<<endl;}
};
class Derived: public Base
{
       public:
           Derived(){ cout<<"C: Derived"<<endl;}        
           ~Derived(){ cout<<"D : Derived"<<endl;}
};

class Derived2: public Derived
{
       public:
           Derived2(){ cout<<"C: Derived2"<<endl;}
           ~Derived2(){ cout<<"D : Derived2"<<endl;}
};

class Derived3: public Derived2
{
       public:
           Derived3(){ cout<<"C: Derived3"<<endl;}
           ~Derived3(){ cout<<"D : Derived3"<<endl;}
};

void main()
{
        Derived *Var = new Derived2();
        delete (Derived3*)Var;  //<---- this should cause some type of run-time error
}

Почему вышеизложенное не вызывает ошибку.Это потому, что в Derived3 нет данных для выпуска.Или я что-то упустил?
Но вместо этого он выводит

C: Base
C: Derived
C: Derived2
D : Derived3       <--- SHOULD NOT BE POSSIBLE
D : Derived2
D : Derived
D : Base

Ответы [ 4 ]

6 голосов
/ 01 апреля 2011

Язык C ++ не имеет обширной системы «ошибок времени выполнения».Некоторые языковые функции могут генерировать исключения или вызывать terminate(), которые действительно являются «ошибками во время выполнения», но недействительные delete не являются одной из этих функций.вызывая неопределенное поведение в C ++.Неопределенное поведение означает, что все может случиться, все возможно.Ваша программа может даже вести себя так, как будто она «работает» каким-то образом.Это то, что вы наблюдаете.

Экспериментировать с неопределенным поведением - бессмысленное упражнение.Результаты, которые вы наблюдаете, ничего не значат и, как правило, не повторяются.

2 голосов
/ 01 апреля 2011

Ваш приведение к Derived3 - это приведение в стиле C, которое фактически совпадает со следующим приведением в стиле C ++.

delete reinterpret_cast<Derived3*>(Var);

Оба этих приведения сообщают среде выполнения C ++, что вы хотите заставить среду выполнения интерпретировать память, на которую ссылается приведение (Var), как данный тип (Derived3*) и полностью понимать последствия. Следовательно, проверка ошибок не выполняется.

Если вас беспокоит законность актерского состава, используйте следующее:

static_cast<Derived3*>(Var): генерирует ошибку компиляции, если приведение неверно. dynamic_cast<Derived3*>(Var): Возвращает 0 (ноль), если приведение неверно.

0 голосов
/ 01 апреля 2011

Неопределенное поведение может делать что угодно, в том числе появляться на работе.Это не работа компилятора или среды выполнения - жаловаться, если вы сделали что-то нелегальное, просто делать правильные вещи, если вы не делали ничего нелегального.

0 голосов
/ 01 апреля 2011

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

В типичном деструкторе вы бы высвободили некоторый ресурс, выделенный этому экземпляру, что вызвало бы ожидаемые проблемы.

При этом это все еще не хороший код, а толькопотому что вы явно приводите неверный тип.Поведение в этом случае технически не определено, что означает, что может произойти все что угодно, включая «работу», как сейчас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...