Если переопределенная функция C ++ вызывает родительскую функцию, которая вызывает другую виртуальную функцию, что называется? - PullRequest
4 голосов
/ 29 июня 2010

Я изучаю полиморфизм, и меня смущает эта ситуация: Допустим, у меня есть следующие классы C ++:

class A{
    ...
    virtual void Foo(){
        Boo();
    }
    virtual void Boo(){...}
}

class B : public A{
    ...
    void Foo(){
        A::Foo();
    }  
    void Boo(){...}
}

Я создаю экземпляр B и вызываю его функцию Foo (). Когда эта функция вызывает A :: Foo (), будет ли использоваться метод Boo () класса A или B? Спасибо!

Ответы [ 3 ]

9 голосов
/ 29 июня 2010

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

class A{
    virtual void Foo(){
        Boo();           // will call the final overrider
        A::Boo();        // will call A::Boo, regardless of the dynamic type
    }
    virtual void Boo();
};
class B : public A{
    void Foo(){
        //Foo();         // Would call the final overrider 
                         // (in this case B: infinite recursion)
        A::Foo();        // Will call A::Foo, even if the object is B
    }  
    void Boo();
};

Неявный указатель this не является важной частьюЗдесь обсуждается то же самое, что и в случае вызова с явным объектом:

B b;
b.Foo();    // will call B::Foo -- note 1
b.A::Foo(); // will call A::Foo

Примечание 1. В этом примере компилятор может исключить механизм динамической отправки, поскольку ему известен конкретный типэкземпляр (он видит определение и не является ссылкой / указателем), но вы можете себе представить, что то же самое произошло бы, если бы b была ссылкой, или эквивалентно, если бы это был указатель с -> вместо .

2 голосов
/ 29 июня 2010

Поскольку Boo() является виртуальным, вызывается переопределение производного класса.

Boo(); - это просто сокращение для this->Boo();, где вы можете видеть, что виртуальная функция вызывается через указатель .(this имеет тип A* const в Foo().) И виртуальные функции, вызываемые через ссылку или указатель, всегда будут вызывать переопределение в наиболее производном классе (кроме случаев, когда они вызываются из конструктора или деструктора).

1 голос
/ 29 июня 2010

Внутри А,

virtual void Foo(){
        Boo();
    }

переводится в this->Boo(), так как Boo объявлен виртуальным в A, вызывается метод Boo производного класса. Попробуйте не объявлять Boo виртуальным в A только для экспериментов - вы увидите, что вызывается A-> Boo ().

Arpan

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