类对象的指针和引用 2022-08-27 06:56 92阅读 0赞 使用类对象的指针和引用——特别是引用,在面向对象编程和函数形参说明方面——特别是后者,非常重要。类对象可能涉及相当多的数据,因此使用按值传递机制(将函数形参指定为对象)可能非常耗时和低效,因为需要复制每一个实参对象。还有一些对类的某些操作而言必不可少的技术也需要使用引用。比如稍后将看到的那样,如果不使用引用形参,我们将不能编写复制构造函数。 **类对象的指针** 我们以声明其他指针的相同方式,声明指向类对象的指针。例如,下面这条语句声明了一个指向CBox类对象的指针: CBox\* pBox = 0; // Declare a pointer to CBox 现在,我们可以在赋值语句中以通常的方式,使用该指针来存储CBox对象的地址: pBox = &cigar; // Store address of CBox object cigar in pBox 正如在Compare()成员函数的定义中使用this指针时所看到的那样,我们可以使用对象的指针来调用函数。例如,我们可以像下面语句中那样通过指针pBox调用函数Volume(): cout << pBox->Volume(); // Display volume of object pointed to by pBox 该语句再次使用了间接成员访问运算符。大多数程序员在这种情况下通常都使用该运算符,因此从现在开始,本书也将大量使用。 试一试:类对象的指针 让我们稍微深入地试着练习一下间接成员访问运算符的用法。我们将使用Ex7\_10.cpp作为基础,但需要作一些修改。 // Ex7\_13.cpp // Exercising the indirect member access operator \#include <iostream> using std::cout; using std::endl; class CBox // Class definition at global scope \{ public: // Constructor definition CBox(double lv = 1.0, double bv = 1.0, double hv = 1.0) \{ cout << endl << "Constructor called."; m\_Length = lv; // Set values of m\_Width = bv; // data members m\_Height = hv; \} // Function to calculate the volume of a box double Volume() const \{ return m\_Length\*m\_Width\*m\_Height; \} // Function to compare two boxes which returns true (1) // if the first is greater that the second, and false (0) otherwise int Compare(CBox\* pBox) const \{ return this->Volume() > pBox->Volume(); \} private: double m\_Length; // Length of a box in inches double m\_Width; // Width of a box in inches double m\_Height; // Height of a box in inches \}; int main() \{ CBox boxes\[5\]; // Array of CBox objects declared CBox match(2.2, 1.1, 0.5); // Declare match box CBox cigar(8.0, 5.0, 1.0); // Declare cigar Box CBox\* pB1 = &cigar; // Initialize pointer to cigar object address CBox\* pB2 = 0; // Pointer to CBox initialized to null cout << endl << "Address of cigar is " << pB1 // Display address << endl << "Volume of cigar is " << pB1->Volume(); // Volume of object pointed to pB2 = &match; if(pB2->Compare(pB1)) // Compare via pointers cout << endl << "match is greater than cigar"; else cout << endl << "match is less than or equal to cigar"; pB1 = boxes; // Set to address of array boxes\[2\] = match; // Set 3rd element to match cout << endl // Now access thru pointer << "Volume of boxes\[2\] is " << (pB1 + 2)->Volume(); cout << endl; return 0; \} 如果运行该示例,则输出看起来与下面显示的大致相似: Constructor called. Constructor called. Constructor called. Constructor called. Constructor called. Constructor called. Constructor called. Address of cigar is 0012FE20 Volume of cigar is 40 match is less than or equal to cigar Volume of boxes\[2\] is 1.21 注意: 当然,您的PC上对象cigar的地址值有可能不同。 **示例说明** 对类定义的修改不是重要的实质性修改。我们只是将Compare()函数改为接受CBox对象的指针作为实参。另外,我们现在知道了关于const成员函数的信息,又因为Compare()函数也不修改对象,所以将其声明为const。main()函数只是以各种相当随意的方式,练习使用CBox对象的指针而已。 在main()函数中,我们在声明过数组Boxes以及CBox对象cigar和match之后,声明了两个CBox对象的指针。第一个指针pB1被初始化为对象cigar的地址,第二个指针pB2被初始化为NULL。这两条语句使用指针的方式与我们使用基本类型的指针时的方式完全相同。我们在使用自定义类型的指针这一事实没有造成任何差别。 我们使用pB1与间接成员访问运算符,获得被指向对象的体积,并将结果显示出来。然后,将match的地址赋给pB2,并在调用比较函数时使用了pB1和pB2两个指针。因为Compare()函数的实参是CBox对象的指针,所以该函数为实参对象调用Volume()函数时使用了间接成员访问运算符。 为了证实使用指针pB1选择成员函数时可以执行地址算术,我们将pB1设定为CBox类型数组boxes中第一个元素的地址。之后,选择数组的第三个元素,并计算其体积。结果与match的体积相同。 从输出可以看出,共有7次对CBox对象构造函数的调用,其中5次是创建数组Boxes,另外创建对象cigar和match各需要一次。 总之,使用类对象的指针与使用基本类型(比如double类型)的指针之间实质上没有任何区别。 **类对象的引用** 当随同类一起使用时,引用才能真正获得应该得到的荣誉。如同指针的情况一样,在声明和使用类对象的引用与声明和使用基本类型变量的引用之间,实质上没有任何区别。例如,为了声明对象cigar的引用,我们可以这样写: CBox& rcigar = cigar; // Define reference to object cigar 为了使用引用计算对象cigar的体积,我们只需在应该出现对象名的位置使用引用名即可: cout << rcigar.Volume(); // Output volume of cigar thru a reference 我们可能还记得,引用扮演着被引用对象别名的角色,因此其用法完全与使用原来的对象名相同。 **1. 实现复制构造函数** 引用的重要性实际体现在函数(特别是类的成员函数)的实参和返回值等上下文中。让我们首先返回到复制构造函数的问题。目前,我们暂且回避何时需要编写自己的复制构造函数这个问题,而全神贯注于如何编写一个复制构造函数的问题。我们将使用CBox类,这仅仅是为了使讨论更具体。 复制构造函数是通过用同类的现有对象进行初始化,从而创建新对象的构造函数,因此需要接受同类的对象作为实参。我们经过考虑,可能写出下面的原型: CBox(CBox initB); 现在,考虑调用该构造函数时将发生什么事情。如果我们写出 CBox myBox = cigar; 这样一条声明语句,那么将生成如下所示对复制构造函数的调用: CBox::CBox(cigar); 在意识到实参是通过按值传递机制传递的之前,该语句似乎没有任何问题。在可以传递对象cigar之前,编译器需要安排创建该对象的副本。因此,编译器为了处理复制构造函数的这条调用语句,需要调用复制构造函数来创建实参的副本。遗憾的是,因为是按值传递,第二次调用同样需要创建实参的副本,因此还得调用复制构造函数,就这样持续不休。我们最终得到的是对复制构造函数的无穷调用。 您肯定已经猜到了,解决方法是使用const引用形参。我们可以将复制构造函数的原型写成下面这样: CBox(const CBox& initB); 现在,计算机再不需要复制复制构造函数的实参。实参是用来初始化引用形参的,因此没有复制发生。我们记得前面关于引用的讨论中说过,如果函数的形参是引用,则调用该函数时不需要复制实参。函数直接访问调用函数中的实参变量。const限定符用来确保该函数不能修改实参。 注意: 这是const限定符的另一个重要用途。我们应该总是将函数的引用形参声明为const,除非该函数将修改实参。 我们可以像下面这样实现这个复制构造函数: CBox::CBox(const CBox& initB) \{ m\_Length = initB.m\_Length; m\_Width = initB.m\_Width; m\_Height = initB.m\_Height; \} 该复制构造函数的定义假定自己位于类定义外部,因此构造函数名用类名和作用域解析运算符加以限定。被创建对象的各个数据成员用传递给构造函数的实参对象的对应成员进行初始化。当然,我们也可以使用初始化列表来设定对象的值。
相关 类对象与类指针 //参考[https://www.cnblogs.com/flylong0204/p/4731318.html][https_www.cnblogs.com_flylong02 迈不过友情╰/ 2023年01月12日 11:56/ 0 赞/ 91 阅读
相关 类对象的指针和引用 使用类对象的指针和引用——特别是引用,在面向对象编程和函数形参说明方面——特别是后者,非常重要。类对象可能涉及相当多的数据,因此使用按值传递机制(将函数形参指定为对象)可能非常 た 入场券/ 2022年08月27日 06:56/ 0 赞/ 93 阅读
相关 指针和引用 1.指针和引用的差别 (1)非空区别:任何情况下都不能使用指向空值的引用。一个引用总是指向某些对象。如果声明一个变量并让它指向一个对象,但是该变量某些时候可能也不指向任何对 迈不过友情╰/ 2022年08月23日 05:52/ 0 赞/ 68 阅读
相关 指针和引用的区别 1.指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元; 引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。 int a=1; 素颜马尾好姑娘i/ 2022年07月16日 10:54/ 0 赞/ 86 阅读
相关 指针和引用的区别 指针存储的是一个地址,指向一个存储单元。引用相当于一个变量的别名。 int a=1;int \p1=&a; int b=2; int &p2=b;//在数据类型名后面出现的 桃扇骨/ 2022年06月13日 07:17/ 0 赞/ 95 阅读
相关 指针和引用的区别 指针和引用的区别 1. 引用 引用是一个对象的别名,主要用于函数参数和返回值类型,引用必须初始化,引用只能在初始化的时候引用一次,不能改变为再引用其他的变量。 男娘i/ 2022年06月06日 13:45/ 0 赞/ 102 阅读
相关 指针和引用 1、引用 1. 引用必须初始化 引用就是给对象取一个别名。定义引用,程序把引用和它的初始值绑定在一起(绑定之后不可再绑定其他对象),而不是初始值拷贝引用,为 ゞ 浴缸里的玫瑰/ 2022年05月31日 01:39/ 0 赞/ 90 阅读
相关 引用和指针的区别 引用:变量的别名,如果别名的值变化,则原始变量的值也随之变化。 指针:指向一块内存地址。 void swap1(int \p1,int \p2)//引用 \{ i 小鱼儿/ 2022年04月03日 10:30/ 0 赞/ 132 阅读
相关 指针和引用的区别 [指针和引用的区别。][Link 1] From :[http://blog.csdn.net/listening\_music/article/details/6921 清疚/ 2022年03月28日 16:42/ 0 赞/ 131 阅读
相关 指针和引用的比较 总述 使用引用(reference)和指针(pointer)都可间接访问另一个值, 但它们之间存在两个重要区别: (1)引用总是指向某个确定对象(事实上,引用就是该对象 Myth丶恋晨/ 2021年12月20日 17:55/ 0 赞/ 190 阅读
还没有评论,来说两句吧...