C++ 类 & 对象

2018-06-17 21:46:11来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

说明:本文章内容大多来源于网络(http://www.runoob.com/cplusplus/cpp-classes-objects.html),在此整理记录自己的学习过程。

一、 简介

1.类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。

2.类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。

二、类成员函数

1.类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。

2.成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符。

 1 class Box
 2 {
 3    public:
 4       double length;      // 长度
 5       double breadth;     // 宽度
 6       double height;      // 高度
 7    
 8       double getVolume(void)
 9       {
10          return length * breadth * height;
11       }
12 };

或者

1 double Box::getVolume(void)
2 {
3     return length * breadth * height;
4 }

三、构造函数

1.类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行

2.构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

四、析构函数

1.类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。

2.析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

注:删除类对象时会调用析构函数;程序跳出对象作用域时会调用析构函数。

五、拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象。

    1 Box box2=box1;

     

  • 复制对象把它作为参数传递给函数。

    1 printwidth(box1);

     

  • 复制对象,并从函数返回这个对象。

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

1 classname (const classname &obj) {//obj 是一个对象引用,该对象是用于初始化另一个对象的。
2    // 构造函数的主体
3 }

六、友元函数

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend,如下所示:

1 class Box
2 {
3    double width;
4 public:
5    double length;
6    friend void printWidth( Box box );
7    void setWidth( double wid );
8 };

声明类 ClassTwo 的所有成员函数作为类 ClassOne 的友元,需要在类 ClassOne 的定义中放置如下声明:

1 friend class ClassTwo;

七、内联函数

1.C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。

2.对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。

3.如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略 inline 限定符。

4.在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。

Tip:

只有当函数只有 10 行甚至更少时才将其定义为内联函数.

定义: 当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制进行调用.

优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.

缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。

结论: 一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!

另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行).

有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要; 比如虚函数和递归函数就不会被正常内联. 通常, 递归函数不应该声明成内联函数.(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数). 虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.

 八、this指针

在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。

友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。

下面的实例有助于更好地理解 this 指针的概念:

 1 #include <iostream>
 2  
 3 using namespace std;
 4 
 5 class Box
 6 {
 7    public:
 8       // 构造函数定义
 9       Box(double l=2.0, double b=2.0, double h=2.0)
10       {
11          cout <<"Constructor called." << endl;
12          length = l;
13          breadth = b;
14          height = h;
15       }
16       double Volume()
17       {
18          return length * breadth * height;
19       }
20       int compare(Box box)
21       {
22          return this->Volume() > box.Volume();
23       }
24    private:
25       double length;     // Length of a box
26       double breadth;    // Breadth of a box
27       double height;     // Height of a box
28 };
29 
30 int main(void)
31 {
32    Box Box1(3.3, 1.2, 1.5);    // Declare box1
33    Box Box2(8.5, 6.0, 2.0);    // Declare box2
34 
35    if(Box1.compare(Box2))
36    {
37       cout << "Box2 is smaller than Box1" <<endl;
38    }
39    else
40    {
41       cout << "Box2 is equal to or larger than Box1" <<endl;
42    }
43    return 0;
44 }

 

编译执行结果

1 Constructor called.
2 Constructor called.
3 Box2 is equal to or larger than Box1

 

九、指向类的指针

一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。

十、类的静态成员

1.使用 static 关键字可以把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。

2.静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。

3.不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化

如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。

静态成员函数只能访问静态成员数据其他静态成员函数类外部的其他函数

静态成员函数有一个类范围,他们不能访问类的 this 指针。您可以使用静态成员函数来判断类的某些对象是否已被创建。

静态成员函数与普通成员函数的区别:

  • 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
  • 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。
 1 #include <iostream>
 2  
 3 using namespace std;
 4 
 5 class Box
 6 {
 7    public:
 8       static int objectCount;
 9       // 构造函数定义
10       Box(double l=2.0, double b=2.0, double h=2.0)
11       {
12          cout <<"Constructor called." << endl;
13          length = l;
14          breadth = b;
15          height = h;
16          // 每次创建对象时增加 1
17          objectCount++;
18       }
19       double Volume()
20       {
21          return length * breadth * height;
22       }
23       static int getCount()
24       {
25          return objectCount;
26       }
27    private:
28       double length;     // 长度
29       double breadth;    // 宽度
30       double height;     // 高度
31 };
32 
33 // 初始化类 Box 的静态成员
34 int Box::objectCount = 0;
35 
36 int main(void)
37 {
38   
39    // 在创建对象之前输出对象的总数
40    cout << "Inital Stage Count: " << Box::getCount() << endl;
41 
42    Box Box1(3.3, 1.2, 1.5);    // 声明 box1
43    Box Box2(8.5, 6.0, 2.0);    // 声明 box2
44 
45    // 在创建对象之后输出对象的总数
46    cout << "Final Stage Count: " << Box::getCount() << endl;
47 
48    return 0;
49 }

 

编译执行结果

1 Inital Stage Count: 0
2 Constructor called.
3 Constructor called.
4 Final Stage Count: 2

 

十一、综合测试实验

执行测试代码,及其输出结果如下所示:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class Box{
 6     double width;//默认访问修饰符为private
 7     double *high;//【当类成员变量是指针时,需在构造函数和拷贝构造函数中为其申请内存,并在析构函数中删除内存】
 8 public:
 9     void setWidth(double wid);
10     void setHigh(double hig);
11     double getHigh( void );
12     Box(double wid, double hig);//构造函数
13     ~Box(void);//析构函数
14     Box(const Box &obj);//拷贝构造函数
15 
16     friend void printwidth(Box box);//友元函数
17 };
18 void Box::setWidth(double wid)
19 {
20     width = wid;
21 }
22 void Box::setHigh(double hig)
23 {
24     *high = hig;
25 }
26 double Box::getHigh( void )
27 {
28     return *high;
29 }
30 Box::Box(double wid, double hig)
31 {
32     cout << "调用构造函数" << endl;
33     width = wid;
34     high = new double;//申请内存
35     *high = hig;
36 }
37 Box::~Box(void)
38 {
39     cout << "调用析构函数并释放内存" << endl;
40     delete high;//释放内存
41 }
42 Box::Box(const Box &obj)
43 {
44     cout << "调用拷贝构造函数" << endl;
45     width = obj.width;
46     high = new double;//申请内存
47     *high = *obj.high;
48 }
49 //友元函数不是类成员变量,但需在类中声明
50 void printwidth(Box box)
51 {
52     cout << "调用友元函数" << endl;
53     cout << "width of box :" << box.width << endl;
54 }
55 void printhigh(Box obj)
56 {
57     cout << "high  of box :" << obj.getHigh() << endl;
58 }
59 //程序主函数
60 int main( )
61 {
62     Box box1(12,15);
63     Box box2=box1;
64 
65     //输出width、high
66     printwidth(box1);
67     printhigh(box1);
68     printwidth(box2);
69     printhigh(box2);
70 
71     //设置width、high
72     box2.setWidth(13);
73     box2.setHigh(16);
74 
75     //输出width、high
76     printwidth(box1);
77     printhigh(box1);
78     printwidth(box2);
79     printhigh(box2);
80 
81     return 0;//调用析构函数(释放box1、box2)
82 }

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:文件输入输出(一):重定向

下一篇:c++ 作业 10月13日 进制转换最简单方法,控制c++输出格式方法 教