Как создать объект абстрактного класса c
Перейти к содержимому

Как создать объект абстрактного класса c

  • автор:

Абстрактные классы (C++)

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

Вы создаете абстрактный класс, объявляя по крайней мере одну чистую виртуальную функцию-член. Это виртуальная функция, объявленная с помощью синтаксиса чистого описателя ( = 0 ). Классы, производные от абстрактного класса, должны реализовывать чисто виртуальную функцию; в противном случае они также будут абстрактными.

Рассмотрим пример, представленный в функциях Virtual. Класс Account создан для того, чтобы предоставлять общие функции, но объекты типа Account имеют слишком общий характер для практического применения. Это означает Account , что это хороший кандидат для абстрактного класса:

// deriv_AbstractClasses.cpp // compile with: /LD class Account < public: Account( double d ); // Constructor. virtual double GetBalance(); // Obtain balance. virtual void PrintBalance() = 0; // Pure virtual function. private: double _balance; >; 

Единственное различие между этим и предыдущим объявлениями состоит в том, что функция PrintBalance объявлена со спецификатором чисто виртуальной функции pure ( = 0 ).

Ограничения на использование абстрактных классов

Абстрактные классы нельзя использовать для:

  • переменных и данных членов;
  • типов аргументов;
  • типов возвращаемых функциями значений;
  • типов явных преобразований.

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

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

Чистые виртуальные функции в абстрактных классах можно определить или реализовать. Такие функции можно вызывать только с помощью полного синтаксиса:

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

// deriv_RestrictionsOnUsingAbstractClasses.cpp // Declare an abstract base class with a pure virtual destructor. // It's the simplest possible abstract class. class base < public: base() <>// To define the virtual destructor outside the class: virtual ~base() = 0; // Microsoft-specific extension to define it inline: // virtual ~base() = 0 <>; >; base::~base() <> // required if not using Microsoft extension class derived : public base < public: derived() <>~derived() <> >; int main() < derived aDerived; // destructor called when it goes out of scope >

В примере показано, как расширение компилятора Майкрософт позволяет добавлять встроенное определение в чистую виртуальную ~base() . Его можно также определить за пределами класса с помощью base::~base() <> .

Когда объект aDerived выходит из область, вызывается деструктор класса derived . Компилятор создает код для неявного вызова деструктора класса base после derived деструктора. Пустая реализация для чистой виртуальной функции ~base гарантирует, что для функции существует хотя бы какая-то реализация. Без него компоновщик создает неразрешенную ошибку внешнего символа для неявного вызова.

В предыдущем примере чистая виртуальная функция base::~base вызывается неявно из derived::~derived . Кроме того, можно явно вызывать чистые виртуальные функции с помощью полного имени функции-члена. Такие функции должны иметь реализацию, или вызов приводит к ошибке во время связи.

Как создать объект абстрактного класса c

Кроме обычных классов в C# есть абстрактные классы . Зачем они нужны? Классы обычно представляют некий план определенного рода объектов или сущностей. Например, мы можем определить класс Car для преставления машин или класс Person для представления людей, вложив в эти классы соответствующие свойства, поля, методы, которые будут описывать данные объекты. Однако некоторые сущности, которые мы хотим выразить с помощью языка программирования, могут не иметь конкретного воплощения. Например, в реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами. И для описания подобных сущностей, которые не имеют конкретного воплощения, предназначены абстрактные классы.

Абстрактный класс похож на обычный класс. Он также может иметь переменные, методы, конструкторы, свойства. Единственное, что при определении абстрактных классов используется ключевое слово abstract . Например, определим абстрактный класс, который представляет некое транспортное средство:

abstract class Transport < public void Move() < Console.WriteLine("Транспортно средство движется"); >>

Транспортное средство представляет некоторую абстракцию, которая не имеет конкретного воплощения. То есть есть легковые и грузовые машины, самолеты, морские судна, кто-то на космическом корабле любит покататься, но как такового транспортного средства нет. Тем не менее все транспортные средства имеют нечто общее — они могут перемещаться. И для этого в классе определен метод Move, который эмулирует перемещение.

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

Transport tesla = new Transport();

Тем не менее абстрактные классы полезны для описания некоторого общего функционала, который могут наследовать и использовать производные классы:

Transport car = new Car(); Transport ship = new Ship(); Transport aircraft = new Aircraft(); car.Move(); ship.Move(); aircraft.Move(); abstract class Transport < public void Move() < Console.WriteLine("Транспортное средство движется"); >> // класс корабля class Ship : Transport < >// класс самолета class Aircraft : Transport < >// класс машины class Car : Transport

В данном случае от класса Transport наследуются три класса, которые представляют различные типы транспортных средств. Тем не менее они имеют общую черту — они могут перемещаться с помощью метода Move() .

Выше писалось, что мы не можем использовать конструктор абстрактного класса для создания экземпляра этого класса. Тем не менее такой класс также может определять конструкторы:

Transport car = new Car("машина"); Transport ship = new Ship("корабль"); Transport aircraft = new Aircraft("самолет"); car.Move(); // машина движется ship.Move(); // корабль движется aircraft.Move(); // самолет движется abstract class Transport < public string Name < get; >// конструктор абстрактного класса Transport public Transport(string name) < Name = name; >public void Move() =>Console.WriteLine($" движется"); > // класс корабля class Ship : Transport < // вызываем конструктор базового класса public Ship(string name) : base(name) < >> // класс самолета class Aircraft : Transport < public Aircraft(string name) : base(name) < >> // класс машины class Car : Transport < public Car(string name) : base(name) < >>

В данном случае в абстрактном классе Transport определен конструктор — с помощью параметра он устанавливает значение свойства Name, которое хранит название транспортного средства. И в этом случае производные классы должны в своих конструкторах вызвать этот конструктор.

Абстрактные члены классов

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

  • Методы
  • Свойства
  • Индексаторы
  • События

Абстрактные члены классов не должны иметь модификатор private. При этом производный класс обязан переопределить и реализовать все абстрактные методы и свойства, которые имеются в базовом абстрактном классе. При переопределении в производном классе такой метод или свойство также объявляются с модификатором override (как и при обычном переопределении виртуальных методов и свойств). Также следует учесть, что если класс имеет хотя бы один абстрактный метод (или абстрактные свойство, индексатор, событие), то этот класс должен быть определен как абстрактный .

Абстрактные члены также, как и виртуальные, являются частью полиморфного интерфейса. Но если в случае с виртуальными методами мы говорим, что класс-наследник наследует реализацию, то в случае с абстрактными методами наследуется интерфейс, представленный этими абстрактными методами.

Абстрактные методы

Например, выше в примере с транспортными средствами метод Move описывает передвижение транспортного средства. Однако различные типы транспорта перемещаются по разному — ездят по земле, летят по воздуху, плывут на воде и т.д. В этом случае мы можем сделать метод Move абстрактным, а его реализацию переложить на производные классы:

abstract class Transport < public abstract void Move(); >// класс корабля class Ship : Transport < // мы должны реализовать все абстрактные методы и свойства базового класса public override void Move() < Console.WriteLine("Корабль плывет"); >> // класс самолета class Aircraft : Transport < public override void Move() < Console.WriteLine("Самолет летит"); >> // класс машины class Car : Transport < public override void Move() < Console.WriteLine("Машина едет"); >>
Transport car = new Car(); Transport ship = new Ship(); Transport aircraft = new Aircraft(); car.Move(); // машина едет ship.Move(); // корабль плывет aircraft.Move(); // самолет летит
Абстрактные свойства

Следует отметить использование абстрактных свойств. Их определение похоже на определение автосвойств. Например:

abstract class Transport < // абстрактное свойство для хранения скорости public abstract int Speed < get; set; >> // класс корабля class Ship: Transport < int speed; public override int Speed < get =>speed; set => speed = value; > > class Aircraft : Transport < public override int Speed < get; set; >>

В классе Transport определено абстрактное свойство Speed, которое должно хранить скорость транспортного средства. Оно похоже на автосвойство, но это не автосвойство. Так как данное свойство не должно иметь реализацию, то оно имеет только пустые блоки get и set. В производных классах мы можем переопределить это свойство, сделав его полноценным свойством (как в классе Ship), либо же сделав его автоматическим (как в классе Aircraft).

Отказ от реализации абстрактных членов

Производный класс обязан реализовать все абстрактные члены базового класса. Однако мы можем отказаться от реализации, но в этом случае производный класс также должен быть определен как абстрактный:

Transport tesla = new Auto(); tesla.Move(); // легковая машина едет abstract class Transport < public abstract void Move(); >// класс машины abstract class Car : Transport<> class Auto: Car < public override void Move() < Console.WriteLine("легковая машина едет"); >>

В данном случае класс Car не реализует абстрактный метод Move базового класса Transport и поэтому также определен как абстрактный. Однако любые неабстрактные классы, производные от Car, все равно должны реализовать все унаследованные абстрактные методы и свойства.

Пример абстрактного класса

Xрестоматийным примером является система геометрических фигур. В реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами:

// абстрактный класс фигуры abstract class Shape < // абстрактный метод для получения периметра public abstract double GetPerimeter(); // абстрактный метод для получения площади public abstract double GetArea(); >// производный класс прямоугольника class Rectangle : Shape < public float Width < get; set; >public float Height < get; set; >// переопределение получения периметра public override double GetPerimeter() => Width * 2 + Height * 2; // переопрелеление получения площади public override double GetArea() => Width * Height; > // производный класс окружности class Circle : Shape < public double Radius < get; set; >// переопределение получения периметра public override double GetPerimeter() => Radius * 2 * 3.14; // переопрелеление получения площади public override double GetArea() => Radius * Radius * 3.14; >
var rectanle = new Rectangle < Width = 20, Height = 20 >; var circle = new Circle < Radius = 200 >; PrintShape(rectanle); // Perimeter: 80 Area: 400 PrintShape(circle); // Perimeter: 1256 Area: 125600 void PrintShape(Shape shape) < Console.WriteLine($"Perimeter: Area: "); >

abstract (Справочник по C#)

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

Пример 1

В этом примере класс Square должен обеспечивать реализацию GetArea , поскольку является производным от класса Shape :

abstract class Shape < public abstract int GetArea(); >class Square : Shape < private int _side; public Square(int n) =>_side = n; // GetArea method is required to avoid a compile-time error. public override int GetArea() => _side * _side; static void Main() < var sq = new Square(12); Console.WriteLine($"Area of the square = "); > > // Output: Area of the square = 144 

Абстрактные классы предоставляют следующие возможности:

  • Создавать экземпляры абстрактного класса нельзя.
  • Абстрактный класс может содержать абстрактные методы и методы доступа.
  • Изменить абстрактный класс с модификатором sealed нельзя, так как два этих модификатора имеют взаимоисключающие значения. Модификатор sealed запрещает наследование класса, в то время как модификатор abstract указывает, что класс обязан иметь производные классы.
  • Неабстрактный класс, производный от абстрактного класса, должен включать фактические реализации всех наследуемых абстрактных методов и методов доступа.

Модификатор abstract в объявлении метода или свойства позволяет указать, что этот метод или свойство не содержат реализации.

Абстрактные методы предоставляют следующие возможности:

  • Абстрактный метод неявно представляет собой виртуальный метод.
  • Объявления абстрактных методов допускаются только в абстрактных классах.
  • Поскольку объявление абстрактного метода не предоставляет фактической реализации, тело метода отсутствует, а объявление метода заканчивается точкой с запятой, и фигурных скобок (< >) после подписи нет. Пример:

public abstract void MyMethod(); 

Действие абстрактных свойств аналогично абстрактным методам, за исключением отличий в синтаксисе объявлений и вызовов.

  • Использование модификатора abstract в статическом свойстве является недопустимым.
  • Абстрактное наследуемое свойство можно переопределить в производном классе, включив объявление свойства, которое использует модификатор override.

Дополнительные сведения об абстрактных классах см. в разделе Абстрактные и запечатанные классы и члены классов.

Абстрактный класс должен предоставлять реализацию для всех членов интерфейса.

Абстрактный класс, реализующий интерфейс, может сопоставлять методы интерфейса с абстрактными методами. Пример:

interface I < void M(); >abstract class C : I

Пример 2

В следующем примере класс DerivedClass является производным от абстрактного класса BaseClass . Абстрактный класс содержит абстрактный метод, AbstractMethod , и два абстрактных свойства, X и Y .

// Abstract class abstract class BaseClass < protected int _x = 100; protected int _y = 150; // Abstract method public abstract void AbstractMethod(); // Abstract properties public abstract int X < get; >public abstract int Y < get; >> class DerivedClass : BaseClass < public override void AbstractMethod() < _x++; _y++; >public override int X // overriding property < get < return _x + 10; >> public override int Y // overriding property < get < return _y + 10; >> static void Main() < var o = new DerivedClass(); o.AbstractMethod(); Console.WriteLine($"x = , y = "); > > // Output: x = 111, y = 161 

В предыдущем примере при попытке создать экземпляр абстрактного класса с помощью оператора вида:

BaseClass bc = new BaseClass(); // Error 

Выдается сообщение об ошибке, указывающее, что компилятор не может создать экземпляр абстрактного класса BaseClass.

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также

  • Справочник по C#
  • Руководство по программированию на C#
  • Модификаторы
  • virtual
  • override
  • Ключевые слова в C#

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

не удается создать экземпляр абстрактного класса или интерфейса «Item» c#

Всё правильно. По законам ООП нельзя создавать экземпляры абстрактного класса. Это как создать человека из мысли о человеке.

Отслеживать
ответ дан 28 мая 2021 в 20:05
Алексей Шиманский Алексей Шиманский
72.1k 12 12 золотых знаков 92 92 серебряных знака 180 180 бронзовых знаков
тем не менее, в лабораторной просят сделать именно так «Реализуйте класс Item как абстрактный»
28 мая 2021 в 20:06

@ававава да ради бога. Только вот создавать надо из реального класса. Т.е. нужно создать ещё класс, который наследуется от абстрактного и уже создавать экземпляр этого самого класса, а не абстрактного

28 мая 2021 в 20:08

Под «реализуйте класс Item как абстрактный» имеется ввиду добавить абстрактный класс Item с некоторыми его членами. Не нужно создавать экземпляр абстрактного класса (этого делать нельзя).

2 ноя 2023 в 6:27
@Danila вы это кому написали?))
2 ноя 2023 в 16:51
@АлексейШиманский, я написал @ав….
4 ноя 2023 в 7:59

не удается создать экземпляр абстрактного класса

/*abstract*/ class Item 

Вслушайтесь в эти слова: «Тиха украинская ночь, прозрачно небо . «

Отслеживать
ответ дан 28 мая 2021 в 20:05
user176262 user176262
тем не менее, в лабораторной просят сделать именно так «Реализуйте класс Item как абстрактный»
28 мая 2021 в 20:06
@ававава Мне сквозь компьютер плохо видно Вашу лабораторную.
– user176262
28 мая 2021 в 20:57

Что бы создать объект класса, класс должен быть не абстрактным. Просто создайте новый класс, которые является наследником Item .

Отслеживать
ответ дан 28 мая 2021 в 20:32
iikuzmychov iikuzmychov
3,067 2 2 золотых знака 10 10 серебряных знаков 28 28 бронзовых знаков
а что я туда должен написать?
28 мая 2021 в 20:34
@ававава class ItemA : Item
28 мая 2021 в 20:35
@ававава а вы можете добавить в ответ всё задание текстом?
28 мая 2021 в 20:36

Реализуйте класс Item как абстрактный  Добавьте ключевое слово abstract при объявлении класса abstract class Item Производные классы не обязаны переопределять виртуальные методы, но если требуется обязать переопределять виртуальный метод, то его следует сде- лать абстрактным. Методы, помеченные как abstract, являются чистым прото- колом: они просто определяют имя, возвращаемый тип (если есть), и набор па- раметров (при необходимости).Реализуйте метод Return как абстрактный  Добавьте ключевое слово abstract при объявлении метода Return базового класса и удалите тело класса:

28 мая 2021 в 20:39

abstract public void Return();  Протестируйте вызов абстрактного метода  В методе Main класса Program вызовите абстрактный метод: 53 Item it; it = b2; it.TakeItem(); it.Return(); it.Show(); it = mag1; it.TakeItem(); it.Return(); it.Show();

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *