Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ C#.docx
Скачиваний:
16
Добавлен:
20.11.2019
Размер:
1.85 Mб
Скачать

3.9. Ссылки на объекты

C# является языком, требующим строгого соблюдения типа при присваивании. Автоматическое преобразование типов, применяемое при работе с обычными переменными, не распространяется на переменные ссылочного типа: ссылочная переменная одного класса не может ссылаться на объект другого класса. Исключение: ссылочной переменой базового класса можно присвоить ссылку на любой класс-наследник. Рассмотрим это на примере.

namespace Virtual1

{

class X

{

public int a;

public X(int i) {a=i;}

}

class Y:X

{

public int b;

public Y(int i, int j ): base(i) {b=j;}

}

class Class1

{

static void Main(string[] args)

{

X x1= new X(10);

X x2;

Y y1=new Y(15,100);

int k;

x2=x1; //допустимо, переменные одного типа

Console.WriteLine("First "+x1.a+" Second "+x2.a);

x2=y1; //допустимо, Y наследник X

Console.WriteLine("First "+x1.a+" Second "+x2.a);

// k=x2.b; ОШИБКА - класс X не имеет переменной b Console.ReadLine(); } } }

Возможность доступа к членам класса зависит от типа ссылочной переменной, а не от типа объекта, на который она ссылается. Поэтому закомментированный оператор будет ошибкой. Наследуемый класс «ничего не знает» о членах класса наследника!

3.10. Конструктор копирования

В общем случае в C# разрешено присвоение между объектами одного и то же класса. На практике это означает, что мы получим два указателя на один и тот же объект. Вспомните, точно так же было и при присвоении массивов. Для обеспечения создания нового объекта, которому в момент создания были переданы значения данных уже существующего объекта, но при этом под него выделялась собственная область памяти и в дальнейшем эти два объекта были бы полностью независимыми, необходим конструктор копирования. Единственным формальным параметром конструктора копирования всегда является переменная типа копируемый класс. При наличии конструктора копирования в классе всегда должен быть и обычный конструктор. Обратите внимание на состав формальных параметров конструктора копирования, и вы поймете, почему это так. Рассмотрим следующий пример.

namespace Construct_Coop

{

class Shape

{

protected double a, h;

public Shape(double x, double y)

{ // обычный конструктор

a = x;

h = y;

}

public Shape(Shape ob)

{ // конструктор копирования

a = ob.a;

h = ob.h;

}

public void NewDan(double x,double y)

{

a = x;

h = y;

}

}

class Tri : Shape

{

protected double area;

public Tri(double x, double y) : base(x, y)

{ // конструктор наследника }

public Tri(Tri ob) :base(ob) // 1

{ // конструктор копирования наследника }

public void Show_area()

{

area = a * h / 2;

Console.WriteLine("S_Treug="+ area);

}

}

class Square : Shape

{

protected double area;

public Square(double x, double y) : base(x, y) { }

public Square(Square ob) : base(ob) { } // 1

public void Show_area()

{

area = a * h;

Console.WriteLine("S_Squar="+ area);

}

}

class Program

{

static void Main(string[] args)

{

Tri my=new Tri(5,12); // работает конструктор

my.Show_area();

Tri w = my; // работает конструктор

w.NewDan(50, 120); // новые данные для w

my.Show_area(); // будут выведены одинаковые значения

w.Show_area();

Tri u = new Tri(w); //работает конструктор копирования

u.NewDan(500, 1200); // новые данные для u

w.Show_area();// будут выведены разные значения

u.Show_area();

Console.ReadLine();

} } }

Обратите внимание на строки // 1: в них имеет место присвоение указателю на базовый класс (Shape) ссылки на класс-наследник (Tri, Square).