深入浅出之抽象与非抽象

一、虚函数&纯需函数

虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。

我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      virtual int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

纯虚函数

您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。

virtual 返回值类型成员函数名(参数表)=0;

class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      // pure virtual function
      virtual int area() = 0;
};

= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数

虚函数和纯虚函数有以下所示方面的区别。

(1)类里如果声明了虚函数,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被覆盖,这样的话,这样编译器就可以使用后期绑定来达到多态了。纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。
(2)虚函数在子类里面也可以不重载的;但纯虚函数必须在子类去实现,这就像Java的接口一样。通常把很多函数加上virtual,是一个好的习惯,虽然牺牲了一些性能,但是增加了面向对象的多态性,因为很难预料到父类里面的这个函数不在子类里面不去修改它的实现。
(4)带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。这样的类也叫抽象类。抽象类和大家口头常说的虚基类还是有区别的,在C#中用abstract定义抽象类,而在C++中有抽象类的概念,但是没有这个关键字。抽象类被继承后,子类可以继续是抽象类,也可以是普通类。

 二、抽象类

     包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。
     在C++中,我们可以把只能用于被继承而不能直接创建对象的类设置为抽象类(Abstract Class)。

     带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。

    抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。

    抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。

    抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个 抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。

抽象类的规定

(1)抽象类只能用作其他类的基类,不能建立抽象类对象。

(2)抽象类不能用作参数类型、函数返回类型或显式转换的类型。

(3)可以定义指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性。

class AbstractCalculator
{
public:
	virtual int getResult() = 0;
	virtual void setOperatorNumber(int a, int b) = 0;
 
};
 
//加法计算器类 一个类只做一件事
class PlusCalculator :public AbstractCalculator
{
public:
	virtual void setOperatorNumber(int a, int b)
	{
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult()
	{
		return mA + mB;
	}
public:
	int mA;
	int mB;
};
 
//减法计算器类
class MinuteCalculator :public AbstractCalculator
{
public:
	virtual void setOperatorNumber(int a, int b)
	{
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult()
	{
		return mA - mB;
	}
public:
	int mA;
	int mB;
};
 
//乘法计算器类
class MultiplyCalculator :public AbstractCalculator
{
public:
	virtual void setOperatorNumber(int a, int b)
	{
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult()
	{
		return mA * mB;
	}
public:
	int mA;
	int mB;
};
 
int main(void)
{
	AbstractCalculator* caculator = new PlusCalculator;
	calculator->setOperatorNumber(10, 20);
	cout << calculator->getResult() << endl;
	delete calculator;
	return 0;
}
 

如果定义如下是错误的

AbstractCalculator* caculator = new AbstractCalculator; //错误

三、抽象类与非抽象类 

抽象类与非抽象类的区别:

1、抽象类可以被继承但不能被实例化(可以引用子类实例化对象),子类继承自抽象类后必须实现该类的所有抽象方法;

2、抽象类中可以有抽象方法和非抽象方法,非抽象类不能有抽象方法,抽象方法一定要被子类重写,而其他方法没要求。

四、抽象类与接口

接口描述了类的行为和功能,而不需要完成类的特定实现。

C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念。

如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是通过在声明中使用 "= 0" 来指定的,如下所示:

class Box
{
   public:
      // 纯虚函数
      virtual double getVolume() = 0;
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};

抽象类和接口的区别:

1、抽象类中可以有实现成员(非抽象方法),而接口中的方法只有声明没有实现;

2、抽象类中可以有字段,接口中不能有字段,但可以有属性;

3、抽象类的成员可以使用公有或其他修饰符,接口中成员是隐式公有的,不需要修饰;

4、抽象类是概念的抽象,接口注重行为,抽象类不支持多重继承,而一个类可以实现多个接口。

五、抽象方法

抽象方法,这种方法只声明返回的数据类型,方法名称和所需要的参数,没有方法体,也就是说抽象方法只需要声明而不需要事先,当一个方法为抽象方法时,意味着这个方法必须被子类的方法所重写,否则其子类的该方法仍然是abstract的,而这个子类也必须是抽象的,即声明为abstract。

 

参考

  1. C++ 抽象类
  2. C#中抽象类和接口
  3. 抽象类和抽象方法总结
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值