В чем разница между конкретным классом и абстрактным классом?


Я изучаю C++, но я запутался в абстрактном классе и конкретном классе. Некоторые примеры реального мира были бы оценены.

9   51   2010-01-27 21:04:12

9 ответов:

абстрактный класс-это класс, для которого один или несколько методов объявлены, но не определены, что означает, что компилятор знает, что эти методы являются частью класса, но не какой код выполнять для этого метода. Они называются абстрактными методами. Вот пример абстрактного класса.

class shape {
public:
  virtual void draw() = 0;
};

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

shape my_shape();
my_shape.draw();

чтобы иметь возможность фактически использовать метод draw, вам нужно будет получить классы из этого абстрактного класса, которые реализуют метод draw, делая классы конкретными:

class circle : public shape {
public:
  circle(int x, int y, int radius) {
    /* set up the circle */
  }
  virtual draw() {
    /* do stuff to draw the circle */
  }
};

class rectangle : public shape {
public:
  rectangle(int min_x, int min_y, int max_x, int max_y) {
    /* set up rectangle */
  }
  virtual draw() {
    /* do stuff to draw the rectangle */
  }
};

теперь вы можете создать экземпляр конкретных объектов круг и прямоугольник и использовать их методы рисования:

circle my_circle(40, 30, 10);
rectangle my_rectangle(20, 10, 50, 15);
my_circle.draw();
my_rectangle.draw();

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

std::vector<shape*> my_scene;
my_scene.push_back(new circle(40, 30, 10));
my_scene.push_back(new rectangle(20, 10, 50, 15));
std::for_each(my_scene.begin(), my_scene.end(), std::mem_fun_ref(&shape::draw)

этот код позволит вам собрать все ваши формы в один контейнер. Это делает его намного проще, если у вас много форм и различных форм сцены. Например, теперь мы можем нарисовать все фигуры за один раз, и код, который делает это, даже не должен знать о различных типах фигур, которые у нас есть.

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

class shape {
public:
  virtual void draw() {
    /* do nothing */
  }
};

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

чтобы ответить на ваш последний вопрос, нет такой вещи, как "нормальный производный класс" каждый класс является либо абстрактным, либо конкретным. Класс, который имеет какие-либо абстрактные методы абстрактные, любой класс, который не является конкретным. Это просто способ различать два типа классов. Базовый класс может быть абстрактным или конкретным, а производный класс может быть абстрактным или конкретным:

class abstract_base {
public:
  virtual void abstract_method1() = 0;
  virtual void abstract_method2() = 0;
};

class concrete_base {
public:
  void concrete_method1() {
    /* do something */
  }
};

class abstract_derived1 : public abstract_base {
public:
  virtual void abstract_method3() = 0;
};

class abstract_derived2 : public concrete_base {
public:
  virtual void abstract_method3() = 0;
};

class abstract_derived3 : public abstract_base {
public:
  virtual abstract_method1() {
    /* do something */
  }
  /* note that we do not provide an implementation for
     abstract_method2 so the class is still abstract */
};

class concrete_derived1 : public concrete_base {
public:
  void concrete_method2() {
    /* do something */
  }
};

class concrete_derived2 : public abstract_base {
public:
  virtual void abstract_method1() {
    /* do something */
  }
  virtual void abstract_method2() {
    /* do something */
  }
  /* This class is now concrete because no abstract methods remain */
};

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

б значит"существующий в реальности или в реальном опыте; воспринимаемый чувствами; реальный". Принимая во внимание, что аннотация означает 'не прикладной и не практический; теоретический'.

An аннотация класс не может быть инстанцирован. Принимая во внимание, что б можно.

An аннотация класс имеет одну или несколько чисто виртуальных функций. В то время как б класс не имеет чисто виртуальных функций.

конкретный класс-это класс, который может быть использован для создания объекта. Абстрактный класс нельзя использовать для создания объекта (необходимо расширить абстрактный класс и создать конкретный класс, чтобы затем создать объект).

представьте, что есть машина, которая может "штамповать" сырье и делать автомобиль. Стампер-это конкретный класс. Из этого мы можем создавать автомобильные объекты. Абстрактный класс будет чертежами для штампа. Вы не можете сделать автомобили из чертежей Стэмпер, вам нужно сначала сделать класс Стэмпера из чертежей.

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

например.Car класса (реферат) в то время как Audi S4 класс (производный от Car) класс-это конкретная реализация.

хороший пример использования абстрактного класса, когда вы строите что-то очень модульный. Допустим, вы работаете с хранилищем данных, но эти данные могут быть в базе данных MySQL, базе данных SQLite, XML-файле или обычном тексте. Чтобы сохранить эту универсальность в коде, можно создать класс AbstractDatastore Это определяет общедоступные методы, которые вы хотите использовать для получения информации из хранилища данных. Затем вы создаете свои конкретные реализации AbstractDatastore, например XmlDatastore,SQLiteDatastore и т. д. Тогда ваш программа просто должна знать, что она получает AbstractDatastore и что он должен иметь те функции, определенные в AbstractDatastore но он не знает и не заботится о том, как данные хранятся или извлекаются.

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

базовый класс-это класс, который не наследуется от любого другого класса. Производный класс наследует от другого класса.

абстрактный класс-это класс, который имеет одну или несколько чистых виртуальных функций. Конкретный класс не имеет чистых виртуалов.

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

C++ Faq Lite Это отличный сайт для поиска ответов на такого рода вопросы.

на уровне проектирования абстрактный базовый класс (ABC) соответствует абстрактному понятию. Если бы вы спросили механика, ремонтирует ли он автомобили, он, вероятно, задался бы вопросом, какой автомобиль вы имеете в виду. Скорее всего, он не ремонтирует космические челноки, океанские лайнеры, велосипеды или атомные подводные лодки. Проблема в том, что термин "транспортное средство" является абстрактным понятием (например, вы не может построить "автомобиль", если вы не знаете, какой автомобиль построить). В C++ класс Vehicle будет ABC, с велосипедом, SpaceShuttle и т. д., являющимися производными классами (OceanLiner-это своего рода транспортное средство). В реальном мире OO, Азбука появляется повсюду

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

 class Shape {
 public:
   virtual void draw() const = 0;  // = 0 means it is "pure virtual"
   ...
 }; 

конкретный класс имеет метод реализован. Абстрактный класс все его методы, за исключением некоторых (по крайней мере, один) метод(ы) не реализованы, так что вы можете расширить его и реализовать не реализованный метод.

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