C++ 具体类和抽象类有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2149207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between a concrete class and an abstract class?
提问by coming out of void
I am learning C++, but I am confused about abstract class and concrete class. Some real world examples would be appreciated.
我正在学习 C++,但我对抽象类和具体类感到困惑。一些现实世界的例子将不胜感激。
回答by wich
An abstract class is a class for which one or more methods are declared but not defined, meaning that the compiler knows these methods are part of the class, but not what code to execute for that method. These are called abstract methods. Here is an example of an abstract class.
抽象类是声明了一个或多个方法但未定义的类,这意味着编译器知道这些方法是类的一部分,但不知道要为该方法执行什么代码。这些被称为抽象方法。下面是一个抽象类的例子。
class shape {
public:
virtual void draw() = 0;
};
This declares an abstract class which specifies that any descendants of the class should implement the draw method if the class is to be concrete. You cannot instantiate this class because it is abstract, after all, the compiler wouldn't know what code to execute if you called member draw. So you can not do the following:
这声明了一个抽象类,该类指定该类的任何后代都应该实现 draw 方法,如果该类是具体的。你不能实例化这个类,因为它是抽象的,毕竟,如果你调用成员绘制,编译器不知道要执行什么代码。所以你不能做以下事情:
shape my_shape();
my_shape.draw();
To be able to actually use the draw method you would need to derive classes from this abstract class, which do implement the draw method, making the classes concrete:
为了能够实际使用 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 */
}
};
Now you can instantiate the concrete objects circle and rectangle and use their draw methods:
现在您可以实例化具体对象圆和矩形并使用它们的绘制方法:
circle my_circle(40, 30, 10);
rectangle my_rectangle(20, 10, 50, 15);
my_circle.draw();
my_rectangle.draw();
Now of course the question is, why would you want to do this? Couldn't you just as well have defined the circle and rectangle classes and have done away with the whole shape class? You could, but then you wouldn't be able to take advantage of their inheritance:
现在当然的问题是,你为什么要这样做?你不能同样定义圆和矩形类并取消整个形状类吗?你可以,但是你将无法利用他们的遗产:
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)
This code let's you collect all your shapes into one container. This makes it a lot easier if you have a lot of shapes and many different shapes in your scene. For example we can now draw all the shapes in one go, and the code that does so doesn't even need to know about the different types of shapes we have.
此代码可让您将所有形状收集到一个容器中。如果你的场景中有很多形状和许多不同的形状,这会让事情变得容易得多。例如,我们现在可以一次性绘制所有形状,这样做的代码甚至不需要知道我们拥有的不同类型的形状。
Now finally we need to know why the draw function of shape is abstract, and not just an empty function, i.e. why didn't we just define:
现在最后我们需要知道为什么shape的draw函数是抽象的,而不仅仅是一个空函数,即为什么我们不直接定义:
class shape {
public:
virtual void draw() {
/* do nothing */
}
};
The reason for this is that we don't really want objects of type shape, they wouldn't be real things anyway, they would be abstract. So it doesn't make any sense to define an implementation for the draw method, even an empty one. Making the shape class abstract prevents us from mistakenly instantiating the shape class, or mistakenly calling the empty draw function of the base class instead of the draw function of the derived classes. In effect we define an interface for any class that would like to behave like a shape, we say that any such class should have a draw method that looks like we have specified it should.
这样做的原因是我们并不真正想要形状类型的对象,无论如何它们都不是真实的东西,它们是抽象的。所以为 draw 方法定义一个实现是没有任何意义的,即使是一个空的。使形状类抽象可以防止我们错误地实例化形状类,或者错误地调用基类的空绘制函数而不是派生类的绘制函数。实际上,我们为任何想要表现得像形状的类定义了一个接口,我们说任何这样的类都应该有一个看起来像我们指定的那样的 draw 方法。
To answer you last question, there isn't any such thing as a 'normal derived class' every class is either abstract or concrete. A class that has any abstract methods is abstract, any class that doesn't is concrete. It's just a way to differentiate the two types of classes. A base class can be either abstract or concrete and a derived class can be either abstract or concrete:
为了回答您的最后一个问题,没有任何诸如“普通派生类”之类的东西,每个类要么是抽象的,要么是具体的。具有任何抽象方法的类是抽象的,任何不具有抽象方法的类都是具体的。这只是区分这两种类的一种方式。基类可以是抽象的或具体的,派生类可以是抽象的或具体的:
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 */
};
回答by Th. Manjit SEMC
Abstract classcan not be used to create an object. Whereas, concrete classcan be used to create an object.
抽象类不能用于创建对象。而具体类可用于创建对象。
Concretemeans''existing in realityor in real experience; perceptible by the senses; real''. Whereas, abstractmeans 'not applied or pratical; theoritical'.
具体是指“存在于现实中或真实体验中”;可通过感官感知;真实的''。鉴于,抽象意味着“不适用或不实用;理论'。
An abstractclass can't be instantiated. Whereas, a concreteone can.
一个抽象类不能被实例化。然而,一个具体的人可以。
An abstractclass is one that has one or more pure virtual function. Whereas a concreteclass has no pure virtual functions.
一个抽象类是具有一个或多个纯虚函数。而具体类没有纯虚函数。
回答by Jansen Price
A concrete class is a class that can be used to create an object. An abstract class cannot be used to create an object (you must extend an abstract class and make a concrete class to be able to then create an object).
具体类是可用于创建对象的类。抽象类不能用于创建对象(您必须扩展抽象类并创建一个具体类才能创建对象)。
Pretend that there is a machine that can "stamp" raw materials and make a car. The stamper is a concrete class. From this we can create car objects. An abstract class would be the blueprints for the stamper. You cannot make cars from the blueprints of the stamper, you need to make the stamper class first from the blueprints.
假设有一台机器可以“冲压”原材料并制造汽车。压模是一个具体的类。由此我们可以创建汽车对象。抽象类将是压模的蓝图。你不能用压模的蓝图制造汽车,你需要先从蓝图制造压模类。
回答by jldupont
An abstract class can't be instantiated whilst a concrete one can. An abstract class serves as "blueprint" for derived classes, ones that can be instantiated.
抽象类不能实例化,而具体类可以。抽象类充当派生类的“蓝图”,派生类可以实例化。
E.g. Car
class (abstract) whilst Audi S4
class (deriving from Car
) class is a concrete implementation.
例如Car
类(抽象)而Audi S4
类(派生自Car
)类是一个具体的实现。
回答by Kelly S. French
A lot of this covered in these other questions:
这些其他问题中涵盖了很多内容:
回答by Diego Dias
C++ Faq Liteis an excellent site to look for answers on this kind of questions.
C++ Faq Lite是寻找此类问题答案的绝佳站点。
At the design level, an abstract base class (ABC) corresponds to an abstract concept. If you asked a mechanic if he repaired vehicles, he'd probably wonder what kind-of vehicle you had in mind. Chances are he doesn't repair space shuttles, ocean liners, bicycles, or nuclear submarines. The problem is that the term "vehicle" is an abstract concept (e.g., you can't build a "vehicle" unless you know what kind of vehicle to build). In C++, class Vehicle would be an ABC, with Bicycle, SpaceShuttle, etc, being derived classes (an OceanLiner is-a-kind-of-a Vehicle). In real-world OO, ABCs show up all over the place
在设计层面,抽象基类 (ABC) 对应于抽象概念。如果你问机械师他是否修理车辆,他可能想知道你想到的是哪种车辆。很有可能他不修理航天飞机、远洋客轮、自行车或核潜艇。问题在于术语“车辆”是一个抽象概念(例如,除非您知道要制造什么样的车辆,否则您无法建造“车辆”)。在 C++ 中,Vehicle 类是 ABC,Bicycle、SpaceShuttle 等是派生类(OceanLiner 是一种交通工具)。在现实世界的面向对象中,ABC 无处不在
An Abstract Class is a class that has one or more pure virtual member functions. You cannot make an object (instance) of an Abstract Class
抽象类是具有一个或多个纯虚成员函数的类。您不能创建抽象类的对象(实例)
class Shape {
public:
virtual void draw() const = 0; // = 0 means it is "pure virtual"
...
};
回答by KeithB
Base-class vs. derived class is an orthogonal concept to abstract class vs. concrete class.
基类与派生类是抽象类与具体类的正交概念。
A base class is one that does not inherit from any other class. A derived class does inherit from another class.
基类是不从任何其他类继承的类。派生类确实从另一个类继承。
An abstract class is one that has one or more pure virtual functions. A concrete class has no pure virtuals.
抽象类是具有一个或多个纯虚函数的类。具体类没有纯虚拟。
An abstract class can be either a base class or a derived class (it is derived from another abstract class). A concrete class can also be either base or derived. You can even derive an abstract class from a concrete class, by adding a pure virtual function to the derived class. But in general use, there is one base abstract class and one or more concrete derived classes.
抽象类可以是基类或派生类(它是从另一个抽象类派生的)。具体类也可以是基类或派生类。通过向派生类添加纯虚函数,您甚至可以从具体类派生抽象类。但在一般使用中,有一个基础抽象类和一个或多个具体派生类。
回答by Corey D
A good example of using an abstract class is when you're building something very modular. Let's say you're working with a data store, but that data could be in a MySQL database, SQLite database, XML file, or plain text. To retain this versatility in your code, you can create a class AbstractDatastore
that defines the public methods you want to use to get information from the datastore. Then you create your specific implementations of the AbstractDatastore
, such as XmlDatastore
, SQLiteDatastore
, etc. Then, your program just needs knows it's getting an AbstractDatastore
and that it must have those functions defined in AbstractDatastore
but it doesn't know or care how the data is stored or retrieved.
使用抽象类的一个很好的例子是当你构建非常模块化的东西时。假设您正在使用数据存储,但该数据可能位于 MySQL 数据库、SQLite 数据库、XML 文件或纯文本中。为了在您的代码中保留这种多功能性,您可以创建一个类AbstractDatastore
来定义要用于从数据存储中获取信息的公共方法。然后创建的特定实现AbstractDatastore
,例如XmlDatastore
,SQLiteDatastore
等等。然后,你的程序只需要知道它得到一个AbstractDatastore
,它必须在定义的那些功能AbstractDatastore
,但它不知道或不关心数据是如何存储或检索。
回答by prashant
Concrete class has all its method implemented. Abstract class all its method except some (at least one) method(s) un-implemented so that you can extend it and implement the un-implemented method.
具体类已实现其所有方法。抽象类除某些(至少一个)未实现的方法外的所有方法,以便您可以扩展它并实现未实现的方法。
Advantage : By extending from abstract class you get all functionality of base class & you will be 'forced' to implement the un-implemented method. So the designer of the class is basically forcing you to write code in the abstract method before the class is of any use to you.
优点:通过从抽象类扩展,您可以获得基类的所有功能,并且您将“被迫”实现未实现的方法。因此,类的设计者基本上是在强迫您在类对您有用之前在抽象方法中编写代码。