Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Виртуальные функции и чистые виртуальные функции




Виртуальный метод (виртуальная функция) — в объектно-ориентированном программировании метод (функция) класса, который может быть переопределён в классах-наследниках так, что конкретная реализация метода для вызова будет определяться во время исполнения. Таким образом, программисту необязательно знать точный тип объекта для работы с ним через виртуальные методы: достаточно лишь знать, что объект принадлежит классу или наследнику класса, в котором метод объявлен.

Виртуальные методы — один из важнейших приёмов реализации полиморфизма. Они позволяют создавать общий код, который может работать как с объектами базового класса, так и с объектами любого его класса-наследника. При этом базовый класс определяет способ работы с объектами и любые его наследники могут предоставлять конкретную реализацию этого способа.

Одни языки программирования (например, C++, C#) требуют явно указывать, что данный метод является виртуальным. В других языках (например, Java, Python) все методы являются виртуальными по умолчанию (но только те методы, для которых это возможно; например в Java методы с доступом private не могут быть переопределены в связи с правилами видимости).

Базовый класс может и не предоставлять реализации виртуального метода, а только декларировать его существование. Такие методы без реализации называются «чистыми виртуальными» или абстрактными. Класс, содержащий хотя бы один такой метод, тоже будет абстрактным. Объект такого класса создать нельзя (в некоторых языках допускается, но вызов абстрактного метода приведёт к ошибке). Наследники абстрактного класса должны предоставить реализацию для всех его абстрактных методов, иначе они, в свою очередь, будут абстрактными классами.

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

Пример виртуальной функции языка C++:

class Ancestor

{

public:

virtual void function1 () { cout << "Ancestor::function1()" << endl; }

void function2 () { cout << "Ancestor::function2()" << endl; }

};

 

class Descendant: public Ancestor

{

public:

virtual void function1 () { cout << "Descendant::function1()" << endl; }

void function2 () { cout << "Descendant::function2()" << endl; }

};

Множественное наследование. Интерфейсы

Множественное наследование - наследование от нескольких базовых классов одновременно.

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

В языке C# подобную проблему позволяют решить интерфейсы. Они играют важную роль в системе ООП. Интерфейсы позволяют определить некоторый функционал, не имеющий конкретной реализации. Затем этот функционал реализуют классы, применяющие данные интерфейсы.

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

Еще один момент в объявлении интерфейса: все его члены - методы и свойства не имеют модификаторов доступа, но фактически по умолчанию доступ public, так как цель интерфейса - определение функционала для реализации его классом. Поэтому весь функционал должен быть открыт для реализации.


 

Практическая часть

Постановка задачи

Цель работы: Разработать программу в среде C++ Builder, прорисовывающую графический объект и реализующую возможность управляемого перемещения, с использованием основных средств ООП в соответствии с заданием.

Программа должна выполнять в общем три задачи:

1. Создание поля для игры.

2. Расположение объектов согласно заданным координатам.

3. Уничтожение объектов по указанным координатам.

4. Вывод результатов игры.

Все полученные результаты отобразить на экране.

Название игры: Морской бой

Правила игра: Сначала необходимо расставить корабли. После расстановки кораблей начинается игра. Игрок поочередно с компьютером стреляют по карте. При попадании даётся ещё один выстрел. Побеждает тот кто уничтожит все корабли первым.

Программирование задачи

Объявление классов в C#.

Класс Places

Это класс карты игры.

public class Places

{

public static int weight, height; // длина и ширина поля

static Places() // статический конструктор класса Places

{

weight = 11;

height = 11;

}

public char[,] map = new char[weight, height]; // поле для игры

 

public void create() // метод создания поля игры

{

for (int i = 1; i < weight; i++)

{

for (int j = 1; j < height; j++)

{

this.map[i, j] = Convert.ToChar("+");

}

}

}

 

}

 

Класс Ships

public class Ships

{

Form1 form;

public int ships_leght;

public int coordX, coordY;

public Ships()

{

coordX = 0;

coordY = 0;

}

 

public Ships(int k)

{

ships_leght = k;

 

}

public virtual void fight_places(Places p)

{

int a = coordX;

int b = coordY;

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

p.map[i, j] = Convert.ToChar("X");

}

 

}

}

 

public virtual void vert(Places p)

{

int a = coordX;

int b = coordY;

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

 

p.map[j, i] = Convert.ToChar("X");

}

//else

//{

// MessageBox.Show("Нельзя так близко ставить корабли", "Близко!", MessageBoxButtons.OK, MessageBoxIcon.Error);

// //form.enter_coordinates(this);

//}

}

}}

В этом классе присутствуют виртуальные методы, которые переопределяются в классе-наследнике.

Класс ShipAI

Это класс-наследник от производного класса Ship.

class ShipAI: Ships

{

Random rand = new Random();

 

public void enter()

{

coordX = rand.Next(1, 9);

coordY = rand.Next(1, 9);

}

public ShipAI(int k): base(k)

{

 

}

 

public void placement()

{

int a = rand.Next(1, 2);

switch(a)

{

case 1: break;

case 2: break;

}

}

public override void fight_places(Places p)

{

enter();

int a = coordX;

int b = coordY;

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

//if ((p.map[i, j]!= Convert.ToChar("X")) && (p.map[i, j + ships_leght]!= Convert.ToChar("X")) && (p.map[i + 1, j]!= Convert.ToChar("X")) && (p.map[i - 1, j]!= Convert.ToChar("X")))

p.map[i, j] = Convert.ToChar("X");

}

}

}

 

public override void vert(Places p)

{

int a = coordY;

int b = coordX;

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

if ((p.map[i, j]!= Convert.ToChar("X")) && (p.map[i + ships_leght, j]!= Convert.ToChar("X")) && (p.map[i, j + 1]!= Convert.ToChar("X")) && (p.map[i, j - 1]!= Convert.ToChar("X")))

{ p.map[j, i] = Convert.ToChar("X"); }

 

}

}

}

}

В этом классе переопределяются методы производного класса. Например такой метод как fight_places(Places p) в классе Ship реализутеся так:

public virtual void fight_places(Places p)

{

int a = coordX;

int b = coordY;

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

p.map[i, j] = Convert.ToChar("X");

}

 

}

}

А в классе ShipAI так:

public override void fight_places(Places p)

{

enter();

int a = coordX;

int b = coordY;

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

if ((p.map[i, j]!= Convert.ToChar("X")) && (p.map[i, j + ships_leght]!= Convert.ToChar("X")) && (p.map[i + 1, j]!= Convert.ToChar("X")) && (p.map[i - 1, j]!= Convert.ToChar("X")))

p.map[i, j] = Convert.ToChar("X");

}

}

}


 

Результаты работы

Рис1. При запуске игры.

 

Рис2. Расстановка кораблей.

 

Рис3.Атака-промах.


 

Заключение

После проделанной работы была освоена технология объектно-ориентированного программирования. В ходе работы была создана компьютерная игра, работающей на платформе.NET Framework. Были приобретены навыки работы в Visual Studio, WinForms, а так же был изучен объектно-ориентированный язык С#.

 


 

Листинг программы

Файл Form1.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

 

namespace WindowsFormsApplication2

{

public partial class Form1: Form

{

static int count = 9;

static int count_2 = 23;

//==================================================================================================================

Places map = new Places();

Places map_AI = new Places();

Ships ship_4 = new Ships(4);

Ships ship_3 = new Ships(3);

Ships ship_2 = new Ships(2);

Ships ship_2_1 = new Ships(2);

Ships ship_2_2 = new Ships(2);

Ships ship_1 = new Ships(1);

Ships ship_1_1 = new Ships(1);

Ships ship_1_2 = new Ships(1);

Ships ship_1_3 = new Ships(1);

//==================================================================================================================

ShipAI shipAI_4 = new ShipAI(4);

ShipAI shipAI_3 = new ShipAI(3);

ShipAI shipAI_2 = new ShipAI(2);

ShipAI shipAI_2_1 = new ShipAI(2);

ShipAI shipAI_2_2 = new ShipAI(2);

ShipAI shipAI_1 = new ShipAI(1);

ShipAI shipAI_1_1 = new ShipAI(1);

ShipAI shipAI_1_2 = new ShipAI(1);

ShipAI shipAI_1_3 = new ShipAI(1);

//===================================================================================================================

public void enter_coordinates(Ships ship)

{

label1.Text = "";

ship.coordX = Convert.ToInt32(textBox1.Text);

ship.coordY = Convert.ToInt32(textBox2.Text);

if (comboBox1.Text == "Вертикально")

{

ship.vert(map);

print(label1, map);

}

else

{

ship.fight_places(map);

print(label1, map);

}

 

}

//===================================================================================================================

public Form1()

{

InitializeComponent();

}

//===================================================================================================================

private void Form1_Load(object sender, EventArgs e)

{

map.create();

map_AI.create();

comboBox1.Items.Add("Вертикально");

comboBox1.Items.Add("Горизонтально");

print(label1, map);

print(label2, map_AI);

}

//===================================================================================================================

private void label3_Click(object sender, EventArgs e)

{

 

}

//===================================================================================================================

private void label1_Click(object sender, EventArgs e)

{

 

}

//===================================================================================================================

private void button1_Click(object sender, EventArgs e)

{

 

enter_for_AI();

//while(count_2!=0)

//{

 

//}

}

//===================================================================================================================

private void button3_Click(object sender, EventArgs e)

{

switches();

count--;

}

//===================================================================================================================

public void switches()

{

switch (count)

{

case 9: enter_coordinates(ship_4); break;

case 8: enter_coordinates(ship_3); break;

case 7: enter_coordinates(ship_2); break;

case 6: enter_coordinates(ship_2_1); break;

case 5: enter_coordinates(ship_2_2); break;

case 4: enter_coordinates(ship_1); break;

case 3: enter_coordinates(ship_1_1); break;

case 2: enter_coordinates(ship_1_2); break;

case 1: enter_coordinates(ship_1_3); break;

}

}

//===================================================================================================================

private void textBox1_TextChanged(object sender, EventArgs e)

{ }

//===================================================================================================================

private void button2_Click(object sender, EventArgs e)

{

Close();

}

//===================================================================================================================

static void print(Label l, Places p)

{

for (int i = 1; i < 11; i++)

{

for (int j = 0; j < 11; j++)

{

l.Text += Convert.ToString(p.map[i, j]) + " ";

}

 

}

}

//===================================================================================================================

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)

{

 

}

//===================================================================================================================

private void button5_Click(object sender, EventArgs e)

{

textBox1.ClearUndo();

textBox1.Text = "";

textBox2.ClearUndo();

textBox2.Text = "";

}

//===================================================================================================================

private void button4_Click(object sender, EventArgs e)

{

attack(map_AI);

}

//===================================================================================================================

public virtual void attack(Places p)

{

int a, b;

a= Convert.ToInt32(textBox1.Text);

b = Convert.ToInt32(textBox2.Text);

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < (b + 1); j++)

{

if (p.map[i, j] == Convert.ToChar("X"))

{

MessageBox.Show("Попадание!", "Попадание", MessageBoxButtons.OK, MessageBoxIcon.Information);

count_2--;

attack(p);

}

else

{

MessageBox.Show("Промах!", "Промах", MessageBoxButtons.OK, MessageBoxIcon.Stop); break;

}

}

}

}

//===================================================================================================================

/// <summary>

///

/// </summary>

public void enter_for_AI()

{

shipAI_4.fight_places(map_AI);

shipAI_3.fight_places(map_AI);

shipAI_2.fight_places(map_AI);

shipAI_2_1.fight_places(map_AI);

shipAI_2_2.fight_places(map_AI);

shipAI_1.fight_places(map_AI);

shipAI_1_1.fight_places(map_AI);

shipAI_1_2.fight_places(map_AI);

}

}

}

 

Файл Ships.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using static System.Console;

public class Ships

{

Form1 form;

public int ships_leght;

public int coordX, coordY;

public Ships()

{

coordX = 0;

coordY = 0;

}

 

public Ships(int k)

{

ships_leght = k;

 

}

public virtual void fight_places(Places p)

{

int a = coordX;

int b = coordY;

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

p.map[i, j] = Convert.ToChar("X");

}

 

}

}

 

public virtual void vert(Places p)

{

int a = coordX;

int b = coordY;

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

 

p.map[j, i] = Convert.ToChar("X");

}

//else

//{

// MessageBox.Show("Нельзя так близко ставить корабли", "Близко!", MessageBoxButtons.OK, MessageBoxIcon.Error);

// //form.enter_coordinates(this);

//}

}

}

 

}

 

Файл Places.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using static System.Console;

public class Places

{

public static int weight, height; // длина и ширина поля

static Places() // статический конструктор класса Places

{

weight = 11;

height = 11;

}

public char[,] map = new char[weight, height]; // поле для игры

 

public void create() // метод создания поля игры

{

for (int i = 1; i < weight; i++)

{

for (int j = 1; j < height; j++)

{

this.map[i, j] = Convert.ToChar("+");

}

}

}

 

}

Файл ShipAI.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using static System.Console;

namespace WindowsFormsApplication2

{

class ShipAI: Ships

{

Random rand = new Random();

 

public void enter()

{

coordX = rand.Next(1, 9);

coordY = rand.Next(1, 9);

}

public ShipAI(int k): base(k)

{

 

}

 

public void placement()

{

int a = rand.Next(1, 2);

switch(a)

{

case 1: break;

case 2: break;

}

}

public override void fight_places(Places p)

{

enter();

int a = coordX;

int b = coordY;

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

// if ((p.map[i, j]!= Convert.ToChar("X")) && (p.map[i, j + ships_leght]!= Convert.ToChar("X")) && (p.map[i + 1, j]!= Convert.ToChar("X")) && (p.map[i - 1, j]!= Convert.ToChar("X")))

p.map[i, j] = Convert.ToChar("X");

}

}

}

 

public override void vert(Places p)

{

int a = coordY;

int b = coordX;

 

for (int i = a; i < (a + 1); i++)

{

for (int j = b; j < b + ships_leght; j++)

{

if ((p.map[i, j]!= Convert.ToChar("X")) && (p.map[i + ships_leght, j]!= Convert.ToChar("X")) && (p.map[i, j + 1]!= Convert.ToChar("X")) && (p.map[i, j - 1]!= Convert.ToChar("X")))

{ p.map[j, i] = Convert.ToChar("X"); }

 

}

}

}

}

}

 


 

Список литературы

1. http://habrahabr.ru/

2. Шилдт Г. С++: базовый курс, третье издание. – К.:Вильямс, 2004., 547 с

3.

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...