Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Медведев_С++_CLI_C#_Java_J#.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
5 Мб
Скачать
☆

Virtual void f ( ) {Console::WriteLine ("a:: f");}

>;

class В : public А

{

public: // Наследуемая виртуальная функция F() переопределяется

Void f ( ) {Console::WriteLine ("b:: f");}

>;

class С : public В

{

public: // Наследуемая виртуальная функция F() переопределяется

Void f ( ) {Console::WrlteLlne ("c:: f");}

>;

class D : public С f

public: // Наследуемая виртуальная функция F() не переопределяется

// vold F ( ) {Console::WrlteLine ("D:: F");}

>;

vcidrnain < )

{

А *pA= new А;

В *pB= new В;

С *pC= new С;

pA -> F ();

pB->F();

pC -> F ( );

pA= pB;

pA -> F ( );

pA= pC;

pA -> F ( );

D *pD= new D;

pA= pD;

pA -> F ( );

>

/*Result:

A:: F

B:: F

C:: F

B:: F

C:: F

C:: F

*/

///////////////

// C#

using System;

c{l ass А/ / Объявление виртуальной функции F()

virtual public void F ( ) {Consoie.WrlteLine("A.F");>

>

class В: А

{ // Наследуемая виртуальная функция F() переопределяется

public override vold F ( ) {Console.WrlteLlne("B.F");}

class С: А

{ // Наследуемая виртуальная функция F() переопределяется

public override void F ( ) {Console.WriteLine("C.F");}

class D: С

{ // Наследуемая виртуальная функция F() не переопределяется

public vold F ( ) {Console.WriteLine("D.F");}

>

class Test

{

static void Maln ()

{

А a= new А ();

В b= new В ( );

С c= new С ( ),

a.F();

b.F();

c.F();

a= b;

a.F();

a= с;

a.F();

D d= new D ( );

a= d;

a.F();

>

>

/*Result:

A.F

B.F

C.F

B.F

C.F

C.F

* /

///////////////

// Java

class А

< // Объявление функции F()

public void F ( ) {System.out.println("A.F");}

>

class В extends А

{ // Наследуемая функция F() переопределяется

public void F ( ) {System.out.println("B.F");>

>

class С extends А

{ // Наследуемая функция F() переопределяется

public void F ( ) {System.out.println("C.F");>

>

class D extends С

{

//public void F ( ) {System.out.printtn("D.F");}

>

class Test

{

public static vold main ( )

{

A a= new A ( );

B b= new B ( );

C c= new C ( );

A r= a;

r.F();

i — и ,

r.F();

r= c;

r.F();

D d= new D ( );

r=d;

r.F();

>

}

/*Result:

A.F

B.F

C.F

C.F

*/

В примере 13.1.2.2 ссылка на базовый класс использована в качестве пара-

метра функции Do(). Аргументы этой функции - ссылки на объекты порож-

дённых классов.

Пример 13.1.2.2. Объявление виртуальной функции в базовом классе.

////c//+//+/// ///////////

#include <stdafx.h>

using namespace System;

class А

{

public:

virtual void F ( ) {Console::WriteLine("A:: F");>

>;

class В : public А

{

public:

Vold f ( ) {Console::WrlteLlne("b:: f");}

>;

class С : public В

{

public:

void F ( ) {Console::WrlteLine("C:: F");>

>;

Vold Do (a* pA)

{

pA -> F ( );

}

Void main ()

{

A *pA= new A;

B *pB= new B;

C *pC= new C;

Do (pA);

Do (pB);

Do (pC);

/>*

Result:

A::F

B::F

C::F

* /

////////////////////

//C#

using System;

class A .

{

public virtual void F ( ) {Console.WriteLineCA.F");>

>

class B: A

<

public override void F ( ) {Console.WriteLine("B.F");}

>

dass С: B

{

public override void F ( ) {Console.WriteLine("C.F");}

>

class Test

{

static void Do (A a)

{

a.F ( );

>

static void Main ( )

{

A a= new А ( );

В b= new В ( );

С c= new С ( );

Do (а);

Do (b);

Do (с);

>

> // *•D»«o•c»i«ilf•r»>•

A.F

B.F

C.F

* /

/ / / / / / / / / / / / / / / / / / / /

// Java

class А

{

public void F ( ) {System.out.println ("A.F");>

>;

class В extends А

{

public void F ( ) {System.out.println ("B.F");}

>;

class С extends В

{

public void F ( ) {System.out.println ("C.F");}

};

class Test

{

static void Do (А а)

{

a.F ( );

>

public static void main ( )

{

А a= new А ();

В b= new В ( );

С c= new С ( );

Do (а);

Do (b);

Do (с);

/>*

Result:

A::F

B::F

C::F

* /

Примеры 13.1.2.1 и 13.1.2.2 подтверждают, что, объявив функцию

виртуальной, мы можем динамически, при необходимости, во время выпол-

нения программы, присвоить ссылке на базовый класс ссылку на требуемый

объекта порождённого класса, и наша программа измснш функционирование,

выполняя виртуальную функцию этого объекта.

Виртуальные функции реализуют так называемое позднее связывание

вызова функции с её телом, осуществляемое во время выполнения програм-

мы. Вызов функции при этом осуществляется косвенно и зависит от типа

объекта.

Так чем же виртуальная функция отличается от обычной функции?

- вызов обычной функции связывается с её телом на этапе компиляции (в от-

личие от виртуальной функции здесь имеет место не косвенное, а прямое об-

ращение к функции), то есть происходит так называемое раннее связывание-,

- при объявлении виртуальной функции перед возвращаемым значением

ставится ключевое слово virtual\

- в языке С++, если некоторая функция объявлена в базовом классе как вир-

туальная, то функция с тем же именем, с тем же возвращаемым значением и с

тем же списком параметров, переопределённая в порождённом классе, авто-

матически становится виртуальной и ключевое слово virtual можно опустить

при её описании;

- в языке C#, если некоторая функция объявлена в базовом классе как вирту-

альная, то функция с тем же именем, с тем же возвращаемым значением и с

тем же списком параметров, переопределённая в порождённом классе с клю-

чевым словом override, автоматически становится виртуальной;

- если виртуальная функция не была переопределена в порождённом классе,

то при её вызове будет происходить обращение к ближайшей соответствую-

щей виртуальной функции по иерархии базовых классов;

- виртуальная функция вызывается только через указатель или ссылку на ба-

зовый класс. Экземпляр вызываемой виртуальной функции определяется

классом объекта, адресуемого указателем или ссылкой, во время выполне-

ния.

Для реализации механизма виртуальных функций компилятор генери-

рует так называемую таблицу виртуальных функций.

Таблица виртуальных функций класса содержит адреса виртуальных функ-

ций, объявленных в классе. В сам класс помещается скрытый указатель на

эту таблицу pvtbl pointer to the virtual table). Если мы имеем несколько объ-

ектов одного класса с виртуальными функциями, то каждый объект будет со-

держать поля с его данными (атрибутами) и указатель на общую для этих

объектов таблицу виртуальных функций. При множественном наследовании

в производном классе могут появиться несколько указателей натаблицы вир-

туальных функций (от базовых классов).