C++面向对象基础快速掌握--自学笔记(二)

这里是C++自学时自己做的笔记,记住C++特有的特性,通用性的不做记录,主要以代码实例加深对定义的枯燥的理解吗,所以重点注意代码中的注释内容,快速了解基础内容,了解代码;

这一章节很重要,前面的基础都是通用,这个是C++特有的面向对象,其他语言的面向对象也是类似,但还是有区别的,掌握这章,C++学的也差不多了


C++ 类 & 对象

C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。

类是 C++ 的核心特性,通常被称为用户定义的类型。

C++ 类定义

定义一个类,这个类特有的属性,如盒子,盒子的属性有长度、宽度、高度
class Box
{
   public:
      double length;   // 盒子的长度
      double breadth;  // 盒子的宽度
      double height;   // 盒子的高度
};
public这个提供访问的权限, private  或  protected用法这里暂不讲解,后续在描述;

定义 C++ 对象

这么说吧,我们定义两个对象:铅笔盒、化妆盒,这两个对象都具有长度、宽度、高度的盒子唯一相同特性;
Box Box1;          // 声明 Box1,类型为 Box---铅笔盒
Box Box2;          // 声明 Box2,类型为 Box---化妆盒

访问数据成员

铅笔盒、化妆盒的两个盒子访问长度、宽度、高度相同公共特性的数据,虽然他们都具备长宽高,但是他们的长宽高都不一样,用途也不一样

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
};
 
int main( )
{
   Box Box1;        // 声明 Box1,类型为 Box--铅笔盒
   Box Box2;        // 声明 Box2,类型为 Box---化妆盒
   double volume = 0.0;     // 用于存储体积
 
   // box 1 详述:铅笔盒的长度、宽度、高度
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;
 
   // box 2 详述:化妆盒的长度、宽度、高度
   Box2.height = 10.0;
   Box2.length = 12.0;
   Box2.breadth = 13.0;
 
   // box 1 的体积---铅笔盒的体积
   volume = Box1.height * Box1.length * Box1.breadth;
   cout << "Box1 的体积:" << volume <<endl;
 
   // box 2 的体积---化妆盒的体积
   volume = Box2.height * Box2.length * Box2.breadth;
   cout << "Box2 的体积:" << volume <<endl;
   return 0;
}
输出:

Box1 的体积:210
Box2 的体积:1560

C++ 继承

面向对象程序设计中最重要的一个概念是继承继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果。

当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类

继承代表了 is a 关系。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物,等等。

基类 & 派生类

一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:

一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名:

class derived-class: access-specifier base-class
假设有一个基类  Shape Rectangle  是它的派生类,案例:

基类和派生类这么理解吧:请看代码内备注,应该会理解

#include <iostream>
 
using namespace std;
 
// 基类:原有Shape( 盒子)定义的两个类:Width(宽度)和)Height(高度)----原来就定义的就是基类,(可以有多个)
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
 
// 派生类:现在又有一个Rectangle(柜子),且柜子有自己独有的Area面积(盒子中没有),就新建定义Area面积,而面积需要宽度和高度来计算,这里宽度和高度shshape盒子中已经含有的,就不用重新在定义了,用盒子的宽度和高度即可(这就是集成)
class Rectangle: public Shape ----继承shape盒子的特性,Rectangle就是派生类
{
   public:
      int getArea()----柜子独有的面积,新建的定义,面积的方法
      { 
         return (width * height); ---借用盒子的宽和高,两个的乘积就是面积
      }
};//这里柜子Rectangle不用在重新写宽度和高了(代码量大的时候,这个可以省不少事),借用已有的来用,新的就新建定义
 //也就是说:现在要柜子面积的属性,需要定义宽度和高度,但是宽度和高度已有就不用重新定义了,只要定义面积即可,引用原有的宽度和高度,这样在主函数中要写什么柜子都可以有面积;---说的有点笼统,要是不明白就看定义

int main(void)//主函数
{
   Rectangle Rect;//矩形柜,这个需要柜子的面积
 
   Rect.setWidth(5);//宽度
   Rect.setHeight(7);//高度
 
   // 输出对象的面积,矩形柜使用柜子的面积Rect.getArea()
   cout << "Total area: " << Rect.getArea() << endl;
 
   return 0;
}
输出:

Total area: 35

访问控制和继承

public(公共的)、protected(保护的)、private(私有的)的用法,在其他语言中用法都类似;

public定义的在任何地方都可以用,private定义的只能在同一个类中使用,protected定义的在外部不能使用;

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。

我们可以根据访问权限总结出不同的访问类型,如下所示:

访问publicprotectedprivate
同一个类yesyesyes
派生类yesyesno
外部的类yesnono

一个派生类继承了所有的基类方法,但下列情况除外(背):

  • 1.基类的构造函数析构函数拷贝构造函数
  • 2.基类的重载运算符
  • 3.基类的友元函数

继承类型

public定义的在任何地方都可以用,private定义的只能在同一个类中使用,protected定义的在外部不能使用;

当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。

我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:

  • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有保护成员来访问。
  • 保护继承(protected): 当一个类派生自保护基类时,基类的公有保护成员将成为派生类的保护成员。
  • 私有继承(private):当一个类派生自私有基类时,基类的公有保护成员将成为派生类的私有成员。

多继承

多继承即一个子类可以有多个父类,它继承了多个父类的特性。

C++ 类可以从多个类继承成员,语法如下:

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};
直接看案例加以理解:(基类和派生类前面解析过了,这里就不重复了)

#include <iostream>
 
using namespace std;
 
// 第一个基类 Shape:“盒子”
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
 
// 第二个基类 PaintCost:“成本”
class PaintCost 
{
   public:
      int getCost(int area)//价格
      {
         return area * 70;//价格用到柜子面积area
      }
};
 
// 派生类,“柜子”继成两个基类,盒子和成本
class Rectangle: public Shape, public PaintCost
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
 
int main(void)
{
   Rectangle Rect;
   int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
 
   area = Rect.getArea();//把柜子利用盒子的宽度和高度算出面积,然后赋予area
   
   // 输出对象的面积:用盒子的宽度和高度算出面积=35
   cout << "Total area: " << Rect.getArea() << endl;
 
   // 输出总花费:area把面积的值带入到价格中去计算area*70=2450
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;
 
   return 0;
}
输出:

Total area: 35
Total paint cost: $2450

继承的另种写法格式

另外多继承(环状继承),A->D, B->D, C->(A,B),例如:

class D{......};
class B: public D{......};
class A: public D{......};
class C: public B, public A{.....};

这个继承会使D创建两个对象,要解决上面问题就要用虚拟继承格式

格式:class 类名: virtual 继承方式 父类名

class D{......};
class B: virtual public D{......};
class A: virtual public D{......};
class C: public B, public A{.....};

虚继承--(在创建对象的时候会创建一个虚表)在创建父类对象的时候

A:virtual public D
B:virtual public D

C++ 重载运算符和重载函数

C++ 允许在同一作用域中的某个函数运算符指定多个定义,分别称为函数重载运算符重载(这个基类不能继承的功能)

重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。

当您调用一个重载函数重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策

C++ 中的函数重载

在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。

下面的实例中,同名函数 print() 被用于输出不同的数据类型:

#include <iostream>
using namespace std;
 
 //基类:
class printData {
 
 public: 
 void print(int i) {
  cout << "整数为: " << i << endl; 
  } 
 
  void print(double f) { 
   cout << "浮点数为: " << f << endl; 
  } 
 
  void print(string c) { 
   cout << "字符串为: " << c << endl; 
  }
}; 
 int main(void){ 
 printData pd;//pd具备基类内的内容 
 
 /*修改基类的参数,这就是函数重载*/ 
 // 输出整数:改变基类整数的值 
 pd.print(5); // 输出浮点数:改变基类浮点数的值 
 pd.print(500.263); // 输出字符串:改变基类字符串的值 
 pd.print("Hello C++"); 
 return 0;
 }
输出:

整数为: 5
浮点数为: 500.263
字符串为: Hello C++

C++ 中的运算符重载

直接上案例,定义看的很烦

#include <iostream>
using namespace std;
 //基类Box
class Box
{
   public:
 
      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }
 
      void setBreadth( double bre )
      {
          breadth = bre;
      }
 
      void setHeight( double hei )
      {
          height = hei;
      }
      // 重载 + 运算符,用于把两个 Box 对象相加
      Box operator+(const Box& b)  //这句话那理解,我也搞不懂(const关键字用法请查看基础常识)
      {
         Box box;
         box.length = this->length + b.length;//Box1的长度+Box2的长度
         box.breadth = this->breadth + b.breadth;//Box1的宽度+Box2的宽度
         box.height = this->height + b.height;//Box1的高度+Box2的高度
         return box;
      }
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
// 程序的主函数
int main( )
{
   Box Box1;                // 声明 Box1,类型为 Box :
   Box Box2;                // 声明 Box2,类型为 Box :
   Box Box3;                // 声明 Box3,类型为 Box :
   double volume = 0.0;     // 把体积存储在该变量中
 
   // Box1 详述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 详述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的体积
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的体积
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // 把两个对象相加,得到 Box3,意思是把Box1的长度+Box2的长度、Box1的宽度+Box2的宽度、Box1的高度+Box2的高度
   Box3 = Box1 + Box2;
 
   // Box3 的体积
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}
输出:

Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400


可重载运算符/不可重载运算符

下面是可重载的运算符列表:

双目算术运算符+ (加),-(减),*(乘),/(除),% (取模)
关系运算符==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于)
逻辑运算符||(逻辑或),&&(逻辑与),!(逻辑非)
单目运算符+ (正),-(负),*(指针),&(取地址)
自增自减运算符++(自增),--(自减)
位运算符| (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移)
赋值运算符=, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
空间申请与释放new, delete, new[ ] , delete[]
其他运算符()(函数调用),->(成员访问),->*(成员指针访问),,(逗号),[](下标)

下面是不可重载的运算符列表:

  • .:成员访问运算符
  • .*->*:成员指针访问运算符
  • :::域运算符
  • sizeof:长度运算符
  • ?::条件运算符
  • #: 预处理符号


C++ 多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
案例:基类和派生类都有area()方法,看看调用哪个
#include <iostream> 
using namespace std;
 
class Shape {//基类Shape
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
//派生类Rectangle
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};
//派生类Triangleclass
class Triangle: public Shape{
   public:
      Triangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};
// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
 
   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();
 
   // 存储三角形的地址
   shape = &tri;
   // 调用三角形的求面积函数 area
   shape->area();
   
   return 0;
}
输出:
都是基类shape中的,因为基类中已经定义过了,这个为主
Parent class area
Parent class area
导致错误输出的原因是,调用函数 area() 被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为 area() 函数在程序编译期间就已经设置好了。
但现在,让我们对程序稍作修改,在 Shape 类中,area() 的声明前放置关键字 virtual(虚函数),如下所示:
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      virtual int area()// 加上关键字 virtual(虚函数)
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
输出:
这次不用调用基类Shape中的
Rectangle class area
Triangle class area
此时,编译器看的是指针的内容,而不是它的类型。因此,由于 tri 和 rec 类的对象的地址存储在 *shape 中,所以会调用各自的 area() 函数。
正如您所看到的,每个子类都有一个函数 area() 的独立实现。这就是多态的一般使用方式。有了多态,您可以有多个不同的类,都带有同一个名称但具有不同实现的函数,函数的参数甚至可以是相同的。


虚函数
虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。


纯虚函数(虚函数=0)
您可能想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
我们可以把基类中的虚函数 area() 改写如下:

lass 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 告诉编译器,函数没有主体,这个虚函数是纯虚函数。
};

C++ 数据抽象
数据抽象 是指只向外界提供关键信息,并隐藏其后台的实现细节,即 只表现必要的信息而不呈现细节
数据抽象是一种依赖于接口和实现分离的编程(设计)技术。
让我们举一个现实生活中的真实 例子 :比如一台电视机,您可以打开和关闭、切换频道、调整音量、添加外部组件(如喇叭、录像机、DVD 播放器),但是您不知道它的内部实现细节,也就是说,您并不知道它是如何通过缆线接收信号,如何转换信号,并最终显示在屏幕上。
因此,我们可以说电视把它的内部实现和外部接口分离开了,您无需知道它的内部实现原理,直接通过它的外部接口(比如电源按钮、遥控器、声量控制器)就可以操控电视。
现在,让我们言归正传,就 C++ 编程而言,C++ 类为数据抽象提供了可能。它们向外界提供了大量用于操作对象数据的公共方法,也就是说, 外界实际上并不清楚类的内部实现
例如,您的程序可以调用 sort() 函数,而不需要知道函数中排序数据所用到的算法。实际上, 函数排序的底层实现会因库的版本不同而有所差异,只要接口不变,函数调用就可以照常工作
在 C++ 中,我们使用类来定义我们自己的抽象数据类型(ADT)。您可以使用类 ostream 的 cout 对象来输出数据到标准输出,案例:
#include <iostream>
using namespace std;
 
int main( )
{
   cout << "Hello C++" <<endl; //在这里,您不需要理解 cout 是如何在用户的屏幕上显示文本。您只需要知道公共接口即可,cout 的底层实现可以自由改变。   //你就只有知道cout是输出的关键字就行,这就是数据抽象
   return 0;
}

访问标签强制抽象
在 C++ 中,我们使用访问标签来定义类的抽象接口。一个类可以包含零个或多个访问标签:
使用公共标签定义的成员都可以访问该程序的所有部分。一个类型的数据抽象视图是由它的公共成员来定义的。
使用私有标签定义的成员无法访问到使用类的代码。私有部分对使用类型的代码隐藏了实现细节。
访问标签出现的频率没有限制。每个访问标签指定了紧随其后的成员定义的访问级别。指定的访问级别会一直有效,直到遇到下一个访问标签或者遇到类主体的关闭右括号为止。
数据抽象的好处
数据抽象有两个重要的优势:
1.类的内部受到保护,不会因无意的用户级错误导致对象状态受损。
2.类实现可能随着时间的推移而发生变化,以便应对不断变化的需求,或者应对那些要求不改变用户级代码的错误报告。
如果只在类的私有部分定义数据成员,编写该类的作者就可以随意更改数据。如果实现发生改变,则只需要检查类的代码,看看这个改变会导致哪些影响。如果数据是公有的,则任何直接访问旧表示形式的数据成员的函数都可能受到影响。
数据抽象的实例
C++ 程序中,任何带有公有和私有成员的类都可以作为数据抽象的实例。请看下面的实例:
#include <iostream>
using namespace std;
 
class Adder{
   public:
      // 构造函数
      Adder(int i = 0)
      {
        total = i;
      }
      // 对外的接口
      void addNum(int number)
      {
          total += number;//total = totakl+number
      }
      // 对外的接口
      int getTotal()
      {
          return total;//getTltal是对外的接口,而这个是通过total实现的(具体怎么实现不能让外部知道)
      };
   private:
      // 对外隐藏的数据,私有成员total 是用户不需要了解的,但又是类能正常工作所必需的。
      int total;
};
int main( )
{
   Adder a;
   
   a.addNum(10);
   a.addNum(20);
   a.addNum(30);
 
   cout << "Total " << a.getTotal() <<endl;
   return 0;
}

输出:
Total 60


抽象设计策略
抽象把代码分离为接口和实现。所以在设计组件时,必须保持接口独立于实现,这样,如果改变底层实现,接口也将保持不变。
在这种情况下,不管任何程序使用接口,接口都不会受到影响,只需要将最新的实现重新编译即可。


C++ 数据封装
所有的 C++ 程序都有以下两个基本要素:
程序语句(代码):这是程序中执行动作的部分,它们被称为函数。
程序数据:数据是程序的信息,会受到程序函数的影响。
封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据隐藏。
数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
C++ 通过创建类来支持封装和数据隐藏(public、protected、private)。我们已经知道,类包含私有成员(private)、保护成员(protected)和公有成员(public)成员。默认情况下,在类中定义的所有项目都是私有的。例如:

class Box
{
   public:
      double getVolume(void)
      {
         return length * breadth * height;
      }
   private:    //以下都是私有的,它们只能被 Box 类中的其他成员访问,而不能被程序中其他部分访问。这是实现封装的一种方式
 //为了使类中的成员变成公有的(即,程序中的其他部分也能访问),必须在这些成员前使用 public 关键字进行声明。所有定义在 public 标识符后边的变量或函数可以被程序中所有其他的函数访问。
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
把一个类定义为另一个类的友元类,会暴露实现细节,从而降低了封装性。理想的做法是尽可能地对外隐藏每个类的实现细节。


数据封装的实例

和上面数据抽象的实例类似,此处略!


封装设计策略
通常情况下,我们都会设置类成员状态为私有(private),除非我们真的需要将其暴露,这样才能保证良好的封装性。
这通常应用于数据成员,但它同样适用于所有成员,包括虚函数。


C++ 接口(抽象类)
接口描述了类的行为和功能,而不需要完成类的特定实现。
C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念。
如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类纯虚函数是通过在声明中使用 "= 0" 来指定的,如下所示:

class Box //抽象类
{
   public:
      // 纯虚函数
      virtual double getVolume() = 0;
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。
因此,如果一个 ABC 的子类需要被实例化,则必须实现每个虚函数,这也意味着 C++ 支持使用 ABC 声明接口。如果没有在派生类中重载纯虚函数,就尝试实例化该类的对象,会导致编译错误。
可用于实例化对象的类被称为具体类


抽象类的实例
请看下面的实例,基类 Shape 提供了一个接口 getArea(),在两个派生类 Rectangle 和 Triangle 中分别实现了 getArea():
#include <iostream>
 
using namespace std;
 
// 基类
class Shape 
{
public:
   // 提供接口框架的纯虚函数
   virtual int getArea() = 0;
   void setWidth(int w)
   {
      width = w;
   }
   void setHeight(int h)
   {
      height = h;
   }
protected:
   int width;
   int height;
};
 
// 派生类
class Rectangle: public Shape
{
public:
   int getArea()
   { 
      return (width * height); 
   }
};
class Triangle: public Shape
{
public:
   int getArea()
   { 
      return (width * height)/2; 
   }
};
 
int main(void)
{
   Rectangle Rect;
   Triangle  Tri;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
   // 输出对象的面积
   cout << "Total Rectangle area: " << Rect.getArea() << endl;
 
   Tri.setWidth(5);
   Tri.setHeight(7);
   // 输出对象的面积
   cout << "Total Triangle area: " << Tri.getArea() << endl; 
 
   return 0;
}
输出:
Total Rectangle area: 35
Total Triangle area: 17


抽象类设计策略
面向对象的系统可能会使用一个抽象基类为所有的外部应用程序提供一个适当的、通用的、标准化的接口。然后,派生类通过继承抽象基类,就把所有类似的操作都继承下来。
外部应用程序提供的功能(即公有函数)在抽象基类中是以纯虚函数的形式存在的。这些纯虚函数在相应的派生类中被实现。
这个架构也使得新的应用程序可以很容易地被添加到系统中,即使是在系统被定义之后依然可以如此。


详情参考:http://www.runoob.com/cplusplus/cpp-classes-objects.html



---------------------------------完,不明白的给我留言·······················
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

测试狂人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值