2016-02-02 3 views
-2

О следующем коде:О виртуальной функции и наследование

class A { 
    A * next; 
    static A* tmp; 
public: 
    A() : next(tmp) { 
     if (tmp) 
      tmp->next = this; 
     tmp = this; 

    } 
    virtual void print() { 
     if (next) 
      next->print(); 
    } 
}; 
class B : public A { 
    int a = 1; 
public: 
    void print() { 
     cout << "foo"; 
     A::print(); 
    } 
}; 
A* A::tmp; 
int main(){ 
    B c; 
    B b; 
    b.print(); 
} 

Почему next->print(); приводит к B::print() и не вернулись к A::print()? Поскольку next является статическим указателем A, почему он переходит на функцию B?

EDIT: добавлено B c;, что я удалил случайно при публикации.

+0

Это странно, на VS15 это происходит в следующем ... @NathanOliver – shinzou

+0

Я удалил строку, когда я разместил это, теперь это не пусто. @NathanOliver – shinzou

+0

@NathanOliver сейчас: https://ideone.com/qnrfUb – shinzou

ответ

1

Поскольку следующий статический указатель A

next не статический указатель. Даже несмотря на то, что у вас может быть инициализирована копия с указателя со статическим хранилищем. Но независимо от того, является ли он статичным, не имеет никакого отношения к тому, как работает вызов функции-члена.

Почему он переходит к функции B?

Потому что print является виртуальной функцией. Если указатель A* next указывает на экземпляр B, то next->print() вызовет B::print(). Это называется виртуальной или динамической отправкой.

Если вы хотите позвонить A::print() вместо этого, то вы могли бы использовать статические отправки:

next->A::print(); 

Конечно, если вы только хотите использовать статические отправки, то это не имеет никакого смысла объявлять функция виртуальная в первую очередь.

+0

Теперь. ОП опубликовал полный пример. Я удалил свой комментарий. – NathanOliver

+0

Но в моем другом вопросе здесь: http://stackoverflow.com/a/35095397/4279201 Мне сказали, что поиск имени основан на статическом типе, поэтому в этом случае не следует указывать указатель 'A' функция 'A', независимо от того, на какой тип она указывает? – shinzou

+0

@kuhaku поиск имени и виртуальная отправка две разные вещи. Имя 'print' отображается только с типа' A', но поскольку это виртуальная функция, вызов будет отправлен практически. – user2079303

2

В вашем коде next->print(); вообще не будет называться. Если вы можете отладить его, вы найдете next здесь.

LIVE

EDIT

С отредактированный кода, процесс будет infinate. next->print(); приведет к B::print(), даже если статический тип next является A*, но A::print() это виртуальная функция, и next указывает на экземпляр B на самом деле, так динамический полиморфизм работает здесь.

+0

@kuhaku 'B :: print()' будет действительно называться. Я попробовал [здесь] (http://rextester.com/JQUHE78947). – songyuanyao

+0

Я удалил важную строку случайно при публикации этого ... – shinzou

Смежные вопросы