具体类和抽象类有什么区别? [英] What is the difference between a concrete class and an abstract class?

查看:40
本文介绍了具体类和抽象类有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 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 */
};

这篇关于具体类和抽象类有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆