C++中不同类型的类(详细指南)

502 阅读6分钟

我们知道,C++是一种面向对象的编程语言。面向对象编程的一个重要方面是类和对象的使用。我们已经涵盖了C++中不同类型的类,如独立类、抽象基类、具体派生类等等。

目录:

  1. 什么是类?
  2. 类的类型
  3. 单独的类
  4. 具体的基类和具体的派生类
  5. 抽象基类和抽象派生类
  6. 抽象基类
  7. 抽象派生类
  8. 朋友类

在我们深入讨论这个话题之前,让我们回顾一下类的基本知识。

什么是类?

一个类是一个用户定义的数据类型。它拥有自己的数据成员和成员函数,可以通过创建该类的一个实例来访问和使用。一个类就像一个对象的蓝图。

we

// 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;
}

输出:这篇文章描述了:类的类型

类的类型

有四种不同类型的类,它们是基于实现而区分的。它们是

  • 单独的类
  • 基础类
  • 派生类
  • 朋友类

有六种不同类型的类是根据定义和用途来区分的。它们是

  • 单独的类
  • 基础类
    • 抽象基类
    • 具体的基类
  • 派生类
    • 抽象派生类
    • 具体的派生类
  • 朋友类

让我们来看看每种类型都是什么。

独立的类

顾名思义,这些类既不是子类(即它们不从任何类中派生出来),也不是父类(即它们不作为基类)。

Class-2

上面给出的例子是关于独立类中的类的声明

// 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;
}

输出:文章的这一部分介绍了,独立的类

具体的基类和具体的派生类

一个具体的类有定义好的成员函数。它们的函数不是虚拟的或纯虚拟的(后面会解释)。

一个具体的基类,顾名思义,是一个拥有定义好的数据成员和函数的类,并作为另一个类派生的基础。一个具体的派生类是一个从现有基类派生出来的具体类。它继承了基类的属性。

c

在上图中,注意到基类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;   

抽象基类

一个包含纯虚函数的类不能用来声明它自己的对象。这样的类被称为抽象基类。

抽象基类的主要目的是为派生类提供功能,并创建用于实现运行时多态性的基础指针。

抽象派生类

一个从抽象基类派生出来的类被称为抽象派生类。抽象派生类的主要目标是继承抽象基类的功能。其余的函数都是虚拟函数。它仍然是一个抽象类,因此该类的对象不能被定义。

注意:只有当派生类的成员函数是虚拟的时候,它才是抽象的:

c2-1

在上图中,算术运算是一个抽象的基类,有纯虚拟函数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被返回。

综上所述,我们已经讨论了不同类型的类和它们的定义。我们已经看到了它们的用途以及何时应用它们。再次强调,类在面向对象编程中是非常重要的。如果使用得好,程序会变得更简单和模块化。编码愉快