問題描述
我正在學習 C++,但我對抽象類和具體類感到困惑.一些真實世界的例子將不勝感激.
I am learning C++, but I am confused about abstract class and concrete class. Some real world examples would be appreciated.
推薦答案
抽象類是聲明了一個或多個方法但未定義的類,這意味著編譯器知道這些方法是類的一部分,但不為該方法執行什么代碼.這些被稱為抽象方法.這是一個抽象類的例子.
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;
};
這聲明了一個抽象類,該類指定該類的任何后代都應該實現 draw 方法,如果該類是具體的.你不能實例化這個類,因為它是抽象的,畢竟,如果你調用成員繪制,編譯器不知道要執行什么代碼.所以你不能做以下事情:
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:
shape my_shape();
my_shape.draw();
為了能夠實際使用 draw 方法,您需要從這個抽象類派生類,這些類確實實現了 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:
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.
現在終于要知道為什么shape的draw函數是抽象的,而不僅僅是一個空函數,即為什么不直接定義:
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:
class shape {
public:
virtual void draw() {
/* do nothing */
}
};
這樣做的原因是我們并不真正想要形狀類型的對象,無論如何它們都不是真實的東西,它們是抽象的.所以為 draw 方法定義一個實現是沒有任何意義的,即使是一個空的.使形狀類抽象可以防止我們錯誤地實例化形狀類,或錯誤地調用基類的空繪制函數而不是派生類的繪制函數.實際上,我們為任何想表現得像形狀的類定義了一個接口,我們說任何這樣的類都應該有一個 draw 方法,看起來就像我們已經指定的那樣.
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.
回答你最后一個問題,沒有任何普通派生類"之類的東西,每個類要么是抽象的,要么是具體的.具有任何抽象方法的類是抽象的,任何不具有抽象方法的類都是具體的.這只是區分這兩種類的一種方式.基類可以是抽象的或具體的,派生類可以是抽象的或具體的:
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 */
};
這篇關于具體類和抽象類有什么區別?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!