С++ для начинающих


         

Виртуальные функции и аргументы по умолчанию


Рассмотрим следующую простую иерархию классов:

#include <iostream>

class base {

public:

   virtual int foo( int ival = 1024 ) {

      cout << "base::foo() -- ival: " << ival << endl;

      return ival;

   }

   // ...

};

class derived : public base {

public:

   virtual int foo( int ival = 2048 ) {

      cout << "derived::foo() -- ival: " << ival << endl;

      return ival;

   }

   // ...

};

Проектировщик класса хотел, чтобы при вызове без параметров реализации foo() из базового класса по умолчанию передавался аргумент 1024:

base b;

base *pb = &b;

// вызывается base::foo( int )

// предполагалось, что будет возвращено 1024

pb->foo();

Кроме того, разработчик хотел, чтобы при вызове его реализации foo() без параметров использовался аргумент по умолчанию 2048:

derived d;

base *pb = &d;

// вызывается derived::foo( int )

// предполагалось, что будет возвращено 2048

pb->foo();

Однако в C++ принята другая семантика механизма виртуализации. Вот небольшая программа для тестирования нашей иерархии классов:

int main()

{

   derived *pd = new derived;

   base *pb = pd;

   int val = pb->foo();

   cout << "main() : val через base: "

        << val << endl;

   val = pd->foo();

   cout << "main() : val через derived: "

        << val << endl;

}

После компиляции и запуска программа выводит следующую информацию:

derived::foo() -- ival: 1024

main() : val через base: 1024

derived::foo() -- ival: 2048

main() : val через derived: 2048

При обоих обращениях реализация foo() из производного класса вызывается корректно, поскольку фактически вызываемый экземпляр определяется во время выполнения на основе типа класса, адресуемого pd и pb. Но передаваемый foo() аргумент по умолчанию определяется не во время выполнения, а во время компиляции на основе типа объекта, через который вызывается функция. При вызове foo() через pb аргумент по умолчанию извлекается из объявления base::foo() и равен 1024. Если же foo() вызывается через pd, то аргумент по умолчанию извлекается из объявления derived::foo() и равен 2048.



Содержание  Назад  Вперед