С++ вызывает виртуальный метод в дочернем классе

у меня есть следующие классы:

class A {
protected:
     A *inner;
public:
    ....
    virtual void doSomething() = 0;
    ....
}

class B: public A {
   ...
   void doSomething() {
       if(inner != NULL)
           inner->doSomething();
   }
   ...
}

Когда я использую inner->doSomething(), я получаю ошибку сегментации. Что мне сделать, чтобы вызвать inner->doSomething() в класс B?

заранее спасибо.


person marcosbeirigo    schedule 30.09.2009    source источник
comment
Если вы получаете segfault при использовании inner, это, вероятно, потому, что он не указывает на допустимый объект. Как вы инициализируете внутренний в B?   -  person Éric Malenfant    schedule 30.09.2009
comment
Каждое A содержит A*? Действительно? Почему?   -  person Daniel Daranas    schedule 30.09.2009
comment
Хорошо, они смотрят друг на друга. Я просто хотел проверить.   -  person Daniel Daranas    schedule 02.10.2009


Ответы (2)


Без явной инициализации внутреннего члена он может быть не NULL и указывать на недопустимую память. Можете ли вы показать нам код, который явно инициализирует внутреннюю часть?

Подходящим конструктором для A будет следующий

protected:
A() : inner(NULL) {
  ...
}
person JaredPar    schedule 30.09.2009
comment
В качестве альтернативы предложению JaredPar в конструкторе укажите, что inner = NULL. Вставьте точку останова в doSomething() подкласса и посмотрите значение inner? - person Calyth; 30.09.2009
comment
не инициализировал его, так как я ожидал, что это будет NULL, а оператор if - ложным. я не знал, что объект может быть не NULL и указывать на недопустимую память. я только что сделал inner = NULL в конструкторе B и решил проблему. большое спасибо. - person marcosbeirigo; 30.09.2009
comment
ВНИМАНИЕ: для всех стандартных типов (указателей, int, float и т. д., также называемых встроенными типами) переменная не инициализируется при построении (нет «конструкторов по умолчанию»). Поскольку «внутренний» является атрибутом A, ответственность за его инициализацию лежит на конструкторе A, иначе у вас возникнет проблема с каждым дочерним классом... - person Matthieu M.; 30.09.2009
comment
Хорошо, Мэтью, я поставлю внутреннюю инициализацию в конструктор А, спасибо! - person marcosbeirigo; 30.09.2009
comment
Можно сократить до A() : inner() { ... }, хотя более явная форма более удобочитаема. - person AnT; 29.06.2013

хотя, если вы назначите A * таким же, как B, инициализировал этот указатель, вы получите переполнение стека ... По какой причине вам нужен внутренний? Разве вы не можете просто вызвать A::DoSomething()?

person Goz    schedule 30.09.2009