2010-01-27 19 views
47

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

+0

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

ответ

88

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

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

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

shape my_shape(); 
my_shape.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 */ 
    } 
}; 

Причина этого заключается в том, что мы не «Мне действительно нужны объекты типа типа, они все равно не были бы реальными вещами, они были бы абстрактными. Поэтому нет смысла определять реализацию метода 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 */ 
}; 
+7

отличное объяснение с простотой ..! –

+0

Если определение функции отсутствует, это просто ошибка ссылки. Абстрактный класс включает = 0, как говорили другие ответы. Хуже того, чистая виртуальная функция * может быть определена в C++. Действительно, определенные, но чистые виртуальные деструкторы являются общими. –

+0

Простые, но покрывает уголок и уголок –

3

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

E.g. Car класс (аннотация) в то время как Audi S4 класс (исходя из) класс представляет собой конкретную реализацию.

+0

Я понятен с абстрактным классом, но в чем разница между нормальным производным классом и конкретным классом? –

18

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

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

+0

почему мы называем это конкретным классом? –

+7

Из-за определения: «Бетон - это« Существующий в реальности или в реальном опыте, ощутимый чувствами, реальный », тогда как абстрактное означает« Не применяется или практично, теоретически » –

0

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

+0

Это не объясняет разницу между абстрактными и конкретными классами, просто когда вы его используете. – wich

+1

Другие люди дали разумные объяснения, я привел пример. –

0

C++ Faq Lite отличный сайт, чтобы искать ответы на этот вид вопросов.

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

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

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

Это не объясняет разницу между абстрактными и конкретными классами, а именно абстрактным классом. – wich

+0

Я прочитал объяснение абстрактного класса как неявное указание того, что такое конкретный класс. Кроме того, C++ FAQ Lite - очень полезный сайт. Следовательно, я взлетел. –

+0

@wich Для меня ясно, что если абстрактный класс является «классом, который имеет одну или несколько чистых виртуальных функций-членов», то конкретный класс является классом, который не является его !!! Или есть полу-абстрактный класс? –

1

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

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

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

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

0

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

Преимущество: Расширяясь от абстрактного класса, вы получаете все функциональные возможности базового класса &, вам будет «принудительно» реализовать не реализованный метод. Поэтому разработчик класса в основном заставляет вас писать код в абстрактном методе, прежде чем класс будет вам полезен.

20

Аннотация Класс не может быть использован для создания объекта. В то время как для создания объекта может использоваться конкретный класс.

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

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

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

Смежные вопросы