![668070aaaa0903a0171cc133e17beed3.png](https://i-blog.csdnimg.cn/blog_migrate/9852eba0de764c942346ee916bea500d.jpeg)
17.创建类的指针成员
17.1指针属性
当你在设计一个类的特征时,类的属性除了可以定义为int、float、char、string类型,也可以尝试使用指针类型来定义类的属性,比如在Animal类中就可以写一个指针类型的属性:ID,用来表示动物的编号,你可以把ID属性声明为float*(编码可以用两段命名法:1.1)或int*(编码用一个整数表示)。
![de86780b9cba413afbc023ccb5fdd94a.png](https://i-blog.csdnimg.cn/blog_migrate/541333f2988ba1c90b2babb29ab2aa44.jpeg)
17.2构造函数
给Animal类添加了一个ID指针属性后,也要在类的构造函数中给对象传值。首先在类的所有构造函数声明和实现中分别增加一个参数float inputID,这样在使用构造函数创建一个动物对象时就可以传入一个新的编号了。
s你需要在每个构造函数的{ }中为这个ID属性分配一个新内存空间,可以使用new运算符动态分配一个堆内存空间。new运算符会开辟并返回新内存的地址,new后面的括号可以放入参数inputID,作为新内存的初始数据值。
![be408c5b3a9ae2bf79770e03dabb73db.png](https://i-blog.csdnimg.cn/blog_migrate/b312c10f4be2f120d7b525dd30b92356.jpeg)
17.3拷贝构造函数
上一节中讲到类中的拷贝构造函数可以写也可以不写,如果不写系统会为你自动生成。但是要注意如果类中写了指针类型的属性后,就一定要实现这个类的拷贝构造函数。
原因在于如果开发者忽略实现这个函数,系统虽然会自动生成拷贝构造函数,但是系统生成的构造函数不会为ID分配新内存,而只是把参数对象的ID的值——地址,赋值给新对象,这样新构造的对象就和参数对象指向了同一个内存空间。这样的话两个对象中如果其中一个对象被析构了,那另一个对象的ID指针就没有合法的内存了。
实现方式为:在函数体中为ID属性动态分配一个新的内存空间,并把参数对象的ID属性值赋给新对象的ID属性。结果是两个对象的ID指针分别指向各自的空间,析构任何一个对象彼此都不影响。
![cd902705b86f040cb1aeb14ea8eaea05.png](https://i-blog.csdnimg.cn/blog_migrate/9f06dec4120c84db3e9120fcde27cf81.jpeg)
17.4赋值运算符
什么时候用到赋值运算符呢?赋值运算符用来把一个对象的数据拷贝给另一个对象。下图中先创建了两个Animal类的对象,然后在139行使用赋值(=)运算符把smallAni02对象的数据拷贝给smallAni01。
![266aec8ed4f4b729c4bf29faba264d9f.png](https://i-blog.csdnimg.cn/blog_migrate/be455380a9ade404cfb721da0b89c2a6.jpeg)
如果类中有指针成员,除了要实现拷贝构造函数外,还有一个函数也必须要实现:重写赋值(=)运算符。
其中的原因如同上面的拷贝构造函数。系统自动生成的赋值(=)运算符,不会为指针ID开辟新空间。当使用赋值运算符给对象赋值时,这个对象已经被构造出来了,所以赋值前需要先释放原来的空间(delete ID),然后再开辟新空间并赋值。(还有另外一种写法你可以思考一下)
![a8d3b0f05272bc0819f53008f0fa13dd.png](https://i-blog.csdnimg.cn/blog_migrate/8b24e371948c0eaded74a69b1e6b700a.jpeg)
17.5析构函数
就像前面介绍的,我们每次构造对象都动态的为ID指针分配了一部分堆内存,那当这个对象被销毁时也必须释放这部分内存,在析构函数中delete ID就可以释放给指针分配的内存。
![045a75d923c7980e1335756f9c745225.png](https://i-blog.csdnimg.cn/blog_migrate/75b92209a9109f12d5548e18e12221d7.jpeg)