C++ 类 & 对象
2018-06-17 21:46:11来源:未知 阅读 ()
说明:本文章内容大多来源于网络(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++ 转换函数搭配友元函数 2020-06-10
- C++ 自动转换和强制类型转换(用户自定义类类型) 2020-06-10
- C++ rand函数 2020-06-10
- C++ 友元函数 2020-06-10
- C++ 运算符重载 2020-06-10
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash