具体类和抽象类之间有什么区别?

com*_*oid 52 c++ oop class

我正在学习C++,但我对抽象类和具体类感到困惑.一些现实世界的例子将不胜感激.

wic*_*ich 98

抽象类是一个声明了一个或多个方法但未定义的类,这意味着编译器知道这些方法是类的一部分,而不是该方法要执行的代码.这些被称为抽象方法.这是一个抽象类的示例.

class shape {
public:
  virtual void draw() = 0;
};
Run Code Online (Sandbox Code Playgroud)

这声明了一个抽象类,它指定类的任何后代应该实现draw方法(如果该类是具体的).您无法实例化此类,因为它是抽象的,毕竟,如果您调用成员绘制,编译器将不知道要执行的代码.所以你不能做到以下几点:

shape my_shape();
my_shape.draw();
Run Code Online (Sandbox Code Playgroud)

为了能够实际使用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 */
  }
};
Run Code Online (Sandbox Code Playgroud)

现在,您可以实例化具体对象circle和rectangle并使用它们的draw方法:

circle my_circle(40, 30, 10);
rectangle my_rectangle(20, 10, 50, 15);
my_circle.draw();
my_rectangle.draw();
Run Code Online (Sandbox Code Playgroud)

当然问题是,你为什么要这样做?难道你不能定义圆形和矩形类并且已经废除了整个形状类吗?你可以,但是你将无法利用他们的继承:

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)
Run Code Online (Sandbox Code Playgroud)

这段代码让你将所有形状收集到一个容器中.如果你的场景中有很多形状和许多不同的形状,这将使它变得容易多了.例如,我们现在可以一次性绘制所有形状,而这样做的代码甚至不需要知道我们拥有的不同类型的形状.

最后我们需要知道为什么shape的draw函数是抽象的,而不仅仅是一个空函数,即为什么我们不定义:

class shape {
public:
  virtual void draw() {
    /* do nothing */
  }
};
Run Code Online (Sandbox Code Playgroud)

这样做的原因是我们并不真正想要类型为对象的对象,无论如何它们都不是真实的东西,它们是抽象的.因此,为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 */
};
Run Code Online (Sandbox Code Playgroud)


小智 23

抽象类不能用于创建对象.而具体类可用于创建对象.

具体意味着" 在现实中或在实际经验中存在; 被感官察觉; 真实''.然而,抽象意味着" 不适用或不实际; 理论上的.

一个抽象类不能被实例化.然而,具体的可以.

一个抽象类是具有一个或多个纯虚函数.而具体类没有纯虚函数.


Jan*_*ice 20

具体类是可用于创建对象的类.抽象类不能用于创建对象(必须扩展抽象类并使具体类能够创建对象).

假装有一台机器可以"盖章"原材料并制造汽车.压模是一个具体的类.由此我们可以创建汽车对象.抽象类将是压模的蓝图.你不能用压模的蓝图制造汽车,你需要先从蓝图上制作压模类.

  • 由于定义:具体是"存在于现实中或在实际经验中;在感官中可感知;真实",而抽象意味着"不适用或不实用;理论上" (8认同)