我们知道,C++是一种面向对象的编程语言。面向对象编程的一个重要方面是类和对象的使用。我们已经涵盖了C++中不同类型的类,如独立类、抽象基类、具体派生类等等。
目录:
- 什么是类?
- 类的类型
- 单独的类
- 具体的基类和具体的派生类
- 抽象基类和抽象派生类
- 抽象基类
- 抽象派生类
- 朋友类
在我们深入讨论这个话题之前,让我们回顾一下类的基本知识。
什么是类?
一个类是一个用户定义的数据类型。它拥有自己的数据成员和成员函数,可以通过创建该类的一个实例来访问和使用。一个类就像一个对象的蓝图。

// C++ program to demonstrate
// declaration of classes
#include <bits/stdc++.h>
using namespace std;
class OpenGenus
{
public: // Access specifier
string str; // Data Members
void printheading() // Member Functions()
{
cout << "This article describes the: " << str;
}
};
int main() {
OpenGenus obj; // Declaring an object of class OpenGenus
obj.str = "Types Of Classes"; // Initializing data member
// accessing member function
obj.printheading();
return 0;
}
输出:这篇文章描述了:类的类型
类的类型
有四种不同类型的类,它们是基于实现而区分的。它们是
- 单独的类
- 基础类
- 派生类
- 朋友类
有六种不同类型的类是根据定义和用途来区分的。它们是
- 单独的类
- 基础类
- 抽象基类
- 具体的基类
- 派生类
- 抽象派生类
- 具体的派生类
- 朋友类
让我们来看看每种类型都是什么。
独立的类
顾名思义,这些类既不是子类(即它们不从任何类中派生出来),也不是父类(即它们不作为基类)。

上面给出的例子是关于独立类中的类的声明
// C++ program to demonstrate
// stand-alone classes
#include <bits/stdc++.h>
using namespace std;
class StandAlone
{
public: // Access specifier
string str; // Data Members
void printheading() // Member Functions()
{
cout << "This section of the article describes the: " << str;
}
};
int main() {
StandAlone obj; // Declaring an object of class OpenGenus
obj.str = "Stand alone classes"; // Initializing data member
// accessing member function
obj.printheading();
return 0;
}
输出:文章的这一部分介绍了,独立的类
具体的基类和具体的派生类
一个具体的类有定义好的成员函数。它们的函数不是虚拟的或纯虚拟的(后面会解释)。
一个具体的基类,顾名思义,是一个拥有定义好的数据成员和函数的类,并作为另一个类派生的基础。一个具体的派生类是一个从现有基类派生出来的具体类。它继承了基类的属性。

在上图中,注意到基类Animal有明确的成员函数(eat(), sleep(), move())。这些函数对所有动物都是通用的。这个类也可以作为一个独立的类来使用。具体的派生类是狗和猫。它们继承了基类动物的数据成员和功能。
举个例子来说明具体的基类和派生类
#include <iostream>
using namespace std;
// Concrete Base Class
class Base {
public:
int a;
};
// Concrete Derived Class
class Derived : public Base {
public:
int b;
};
// Driver Code
int main()
{
Derived obj;// Initialise an object of derived class
obj.b = 3;// Assign value to Derived class variable
obj.a = 4; // Assign value to Base class variable via derived class
cout << "Value from derived class: "<< obj.b << endl;
cout << "Value from base class: "<< obj.a << endl;
return 0;
}
输出:
来自派生类的值:3
来自派生类的值:4
具体的基类和具体的派生类之间的区别
| 具体的基类 | 具体派生类 |
|---|---|
| 有助于派生或创建新的类 | 从基类中派生出来 |
| 也被称为父类 | 也叫子类 |
| 不能继承子类的属性和方法 | 可以继承父类的属性和方法 |
| 可以作为独立的类使用 | 不能作为独立的类使用 |
抽象基类和抽象派生类
在我们深入探讨类的定义之前,首先让我们了解什么是虚拟函数和纯虚拟函数。
虚函数
对虚拟函数的需求。
考虑下面给出的例子,它有一个具体的基类和具体的派生类:
#include <iostream>
using namespace std;
class A //concrete base class
{
int x=10;
public:
void display()
{
cout << "Value of x is : " << x<<endl;
}
};
class B: public A //concrete derived class
{
int y = 15;
public:
void display()
{
cout << "Value of y is : " <<y<<endl;
}
};
int main()
{
A* a; //pointer of base class
B b; //object of derived class
a = &b;
a->display();
return 0;
}
在上面的程序中,输出是:x的值是:10。
a是具体基类的指针。a只能访问基类的数据成员,而不能访问派生类的成员。尽管C++允许基类指针指向任何从基类派生的对象,但它不能直接访问派生类的成员。
因此,需要一种特殊类型的函数,允许基指针访问派生类的成员。这种类型的函数被称为虚拟函数。
一个虚拟函数的例子:
#include <iostream>
using namespace std;
class A //concrete base class
{
int x=10;
public:
virtual void display()
{
cout << "Value of x is : " << x<<endl;
}
};
class B: public A //concrete derived class
{
int y = 15;
public:
void display()
{
cout << "Value of y is : " <<y<<endl;
}
};
int main()
{
A* a; //pointer of base class
B b; //object of derived class
a = &b;
a->display();
return 0;
}
在上面的例子中,输出是。y的值是:15
纯虚拟函数
需要纯虚拟函数。
纯虚函数(或称 "无为 "函数)不用于执行任何任务。纯虚函数是一个在基类中声明的函数,在基类中没有定义。下面的例子显示了一个纯虚函数:
virtual void show() = 0;
抽象基类
一个包含纯虚函数的类不能用来声明它自己的对象。这样的类被称为抽象基类。
抽象基类的主要目的是为派生类提供功能,并创建用于实现运行时多态性的基础指针。
抽象派生类
一个从抽象基类派生出来的类被称为抽象派生类。抽象派生类的主要目标是继承抽象基类的功能。其余的函数都是虚拟函数。它仍然是一个抽象类,因此该类的对象不能被定义。
注意:只有当派生类的成员函数是虚拟的时候,它才是抽象的:

在上图中,算术运算是一个抽象的基类,有纯虚拟函数add(), subtract(), multiply() , divide()。它引用了整数、矩阵和其他运算派生类。
这样实现的原因是,尽管我们可以对整数和矩阵进行同样的4个算术运算,但这两个类的运算定义不同。由于四个函数add(), subtract(), multiply() , divide()在integers和multiply中被覆盖了,它们是具体的派生类
在派生类中,其他操作,四个基本的纯虚拟函数没有被覆盖,尽管它是从操作类中派生出来的。相反,其他虚拟函数被引入。因此,其他操作是一个抽象的派生类,这个类的对象不能被创建。
举个例子来说明抽象类的工作原理
#include <iostream>
using namespace std;
class A //abstract base class
{
public:
virtual void show() = 0; //pure virtual function
};
class B : public A // derived class
{
public:
void show()
{
cout << "This is the derived class" << endl;
}
};
int main()
{
A *a;
B b;
a = &b;
a->show();
return 0;
}
输出:这就是派生类
抽象基类和抽象派生类之间的区别
| 抽象基类 | 抽象派生类 |
|---|---|
| 有助于派生或创建新的类 | 从基类中派生出来的 |
| 也被称为父类 | 也叫子类 |
| 该类包含纯虚拟函数 | 这个类包含虚拟函数 |
让我们考虑一个例子来理解抽象派生类和具体派生类之间的区别:
class abstract_base {
public:
virtual void abstract_method1() = 0;
virtual void abstract_method2() = 0;
};
class concrete_base {
public:
void concrete_method1() {
/* random code */
}
};
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() {
/* random code */
}
};
class concrete_derived1 : public concrete_base {
public:
virtual void abstract_method1() {
/* random code */
}
virtual void abstract_method2() {
/* random code */
}
/* This class is now concrete because no abstract methods remain */
};
class example : public abstract_base {
public:
virtual void abstract_method2() {
/* random code */
}
};
注意,我们没有为abstract_method1和abstract_method2提供实现,所以abstract_derived类仍然是抽象的,这个类的对象不能被创建。
问题
上述程序中的例子是哪种类型的类?
具体的派生类
抽象派生类
具体的基类
抽象基类
类example是一个具体的派生类,尽管它是从一个抽象类派生出来的。这是因为其中的一个纯虚拟基函数被覆盖了,而且在类的定义中没有现有的虚拟函数。可以创建一个问题类的对象
朋友类
对友方类的需求
数据封装是面向对象编程的一个重要概念。它限制了来自类外的私有成员的访问。
同样地,受保护的成员只能由派生类访问,外部无法访问。比如说:
class A {
private:
int num;
}
int main() {
A obj;
A.num = 5;// Private data members cannot be accessed from here
}
友好函数
一个朋友函数可以访问一个类的私有和受保护数据。我们在类的主体中使用 friend 关键字来声明一个朋友函数。下面是一个友方函数的例子
class className {
... .. ...
friend returnType functionName(arguments);
... .. ...
}
与友方函数类似,我们也可以在C++中使用友方关键字来使用友方类。比如说:
class ClassFriend;
class ClassA {
// ClassFriend is a friend class of ClassA
friend class ClassFriend;
... .. ...
}
class ClassFriend {
... .. ...
}
当一个类被声明为朋友类时,朋友类的所有成员函数都变成了朋友函数。由于ClassFriend是一个朋友类,我们可以从ClassFriend内部访问ClassA的所有成员。
注意:我们不能从ClassA内部访问ClassFriend的成员。这是因为C++中的朋友关系是只给不取的。
一个描述使用朋友类的例子
#include <iostream>
using namespace std;
class Square
{
protected:
int side;
friend class Rectangle;
public:
Square (int s) // parameterised constructor
{
side = s;
}
};
class Rectangle{
int length;
int breadth;
public:
int getArea(){
return length*breadth;
}
void shape(Square a){
length = a.side;
breadth = a.side;
}
};
int main(){
Square square(5);
Rectangle rectangle;
rectangle.shape(square);
cout<<rectangle.getArea()<<endl;
return 0;
}
输出:25
在上面的程序中,Rectangle是Square类的友方函数,side是Square类的保护成员。它被Rectangle访问。当square(5)类的对象被创建时,side被初始化为5。然后我们创建矩形类的矩形对象。然后它访问Square的边,并将长度和宽度初始化为5。当函数getArea()被调用时,长度*宽度=25被返回。
综上所述,我们已经讨论了不同类型的类和它们的定义。我们已经看到了它们的用途以及何时应用它们。再次强调,类在面向对象编程中是非常重要的。如果使用得好,程序会变得更简单和模块化。编码愉快