类和对象的使用之对象指针

1、对象指针的一般概念

对象指针:指向类的成员的指针。在C++中,可以说明指向类的数据成员和成员函数的指针。

对象指针遵循一般变量指针的各种规则:类名 *对象指针名;

对象指针名à成员名;

对象指针在使用之前,也一定要先进行初始化,让它指向一个已经声明过的对象,然后再使用。通过对象指针,可以访问到所指向对象的公有成员。

2.指向对像的指针
在建立对像时,编译系统会为每一个对像分配一定的存储空间,以存放其成员,对像空间的起始地址就是
对像的指针。可以定义一个指针变量,用来存和对像的指针。如果有一个类:

class Time
{
   public:
 int hour;
        int minute;
        int sec;
        void get_time();
};
void Time::get_time()
{
   cout << hour << ":" << minute << ":" << sec << endl;
}

在此有以下语句:

Time *pt;//定义pt 为指向Time类对像的指针变量
Time t1;//定义t1为Time类对像
pt=&t1;//将t1的起始地址赋给pt

这样,pt 就是指向Time类对象的指针变量,它指向对象t1。
定义指向类对象的指针变量的一般形式为:

类名 *对象指针名;

可以通过对象指针访问对象和对象的成员。如:

*pt       pt所指向的对像,即t1
(*pt).hour      pt所指向的对象中的hour成员,即t1.hour
pt->get_time()  pt把指向的对象中的get_time函数,即t1.get_time()
(*pt).get_time()

3.指向对象成员的指针

a.指向对象数据成员的指针
定义指向对象数据成员的指针的方法与定主指向变通的指针变量的方法相同。如:
int *p;

定义指向对象数据成员的指针变量的一般形式为:

数据类型名 *指针变量名;

b.指向对象成员函数的指针

定义指向对象成员函数的指针变量的方法和定义指向变通函数的指针变量方法有所不同。
定义指向变通函数的指针变量的方法:

数据类型名  (*指针变量名)();如:
void (*p)();//p是指向void型函的指针变量

定义指向成员函的指针:

数据类型名 (类名::*指针变量名)();
使指针变量指向一个公用成员函数的一般形式为
指针变量名=&类名::成员函数名;

示例:

 1 #include <iostream>
 2 using namespace std;
 3 class Time
 4 {
 5  public:
 6   Time(int ,int ,int );
 7   int hour;
 8   int minute;
 9   int sec;
10   void get_time();
11 };
12 Time::Time(int h,int m,int s)
13 {
14  hour = h;
15  minute= m;
16  sec = s;
17 }
18 void Time::get_time()
19 {
20  cout << hour << ":" << minute << ":" << sec << endl;
21 }
22
23 int main()
24 {
25  Time t1(10,13,56); //定义Time类对象t1
26  int *p1=&t1.hour;//定义指向整型数据的指针变量p1,并使p1指向t1.hour
27  cout << *p1 << endl;
28  t1.get_time();//调用对象t1的成员函数get_time()
29
30  Time *p2=&t1;//定义指向Time类对象的指针变量p2,并使p2指向t1
31  p2->get_time();//调用p2所指向对象的get_time()函数
32  void (Time::*p3)();//定义指向Time类公用成员函数get_time
33  p3 = &Time::get_time;//使p3指向Time类公用成员函数get_time
34  (t1.*p3)();//调用对象t1中p3所指的成员函数
35
36  return 0;
37 }

4、指向类的非静态成员的指针(非指向对象,而是指向对象成员)

指向对象成员的指针使用前也要先声明,再赋值,然后引用,因此首先要声明指向该对象所在类的成员的指针。注意,通过指向成员的指针也只能访问到公有成员。

语法形式:类型说明符   类名::*指针名;          //声明指向公有数据成员的指针

             类型说明符   (类名::*指针名)(参数表);//声明指向公有函数成员的指针

对数据成员指针赋值:

指针名 = &类名::数据成员;

此时还不能通过指针访问变量。类的声明只确定了各个数据成员的类型、所占内存大小以及它们的相对位置,在声明时并不为数据成员分配具体的地址。因此经上述赋值之后,只是说明了被赋值的成员指针式专门用于指向哪个数据成员的,同时在指针中存放该数据成员在类中的相对位置,当然通过这样的指针现在并不能访问什么。

由于类是通过对象而实例化的,在声明类的对象时才会为具体的对象分配内存空间,这时只要将对象在内存中的起始地址与成员指针中存放的相对偏移结合起来就可以访问到对象的数据成员了。

语法形式:对象名.*类成员指针名

        或          对象指针名à*类成员指针名

       成员函数指针赋值:

指针名 = 类名::函数成员名;

       经过上述对成员函数指针赋值之后,还不能用指针直接调用成员函数,而是需要首先声明类的对象,因为必须要通过对象来调用非静态成员函数。

       利用指针调用成员函数:

                      (对象名.*类成员指针名)(参数表)

或      (对象指针名à*类成员指针名)(参数表)

5、指向类的静态成员的指针

       类的静态成员可以用普通的指针来指向和访问。/**形式上把静态成员看成普通变量就可以**/

对象指针:在C++中,可以说明指向类的数据成员和成员函数的指针。

1. 对象指针作函数的参数

使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针作函数参数有如下两点好处:

(1) 实现传址调用。可在被调用函数中改变调用函数的参数对象的值,实现函数之间的信息传递。

(2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少时空开销。

当形参是指向对象指针时,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针作函数参数。

 1 #include <iostream.h>
 2     class M
 3     {
 4     public:
 5         M() { x=y=0; }
 6         M(int i, int j) { x=i; y=j; }
 7         void copy(M *m);
 8         void setxy(int i, int j) { x=i; y=j; }
 9         void print() { cout<<x<<","<<y<<endl; }
10     private:
11         int x, y;
12     };
13
14     void M::copy(M *m)
15     {
16     x=m->x;
17     y=m->y;
18     }
19
20     void fun(M m1, M *m2);
21     void main()
22     {
23     M p(5, 7), q;
24     q.copy(&p);
25     fun(p, &q);
26     p.print();
27     q.print();
28     }
29
30     void fun(M m1, M *m2)
31     {
32     m1.setxy(12, 15);
33     m2->setxy(22,25);
34     }
35
36     输出结果为:
37     5,7
38     22,25

  从输出结果可以看出,当在被调用函数fun中,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。

2. 对象引用作函数参数

在实际中,使用对象引用作函数参数要比使用对象指针作函数更普遍,这是因为使用对象引用作函数参数具有用对象指针作函数参数的优点,而用对象引用作函数参数将更简单,更直接。所以,在C++编程中,人们喜欢用对象引用作函数参数。现举一例子说明对象引用作函数参数的格式。

 1 #include <iostream.h>
 2     class M
 3     {
 4     public:
 5         M() { x=y=0; }
 6         M(int i, int j) { x=i; y=j; }
 7         void copy(M &m);
 8         void setxy(int i, int j) { x=i; y=j; }
 9         void print() {cout<<x<<","<<y<<endl; }
10     private:
11         int x, y;
12     };
13
14     void M::copy(M &m)
15     {
16         x=m.x;
17         x=m.y;
18     }
19
20     void fun(M m1, M &m2);
21
22     void main()
23     {
24         M p(5, 7), q;
25         q.copy(p);
26         fun(p, q);
27         p.print();
28         q.print();
29     }
30
31     void fun(M m1, M &m2)
32     {
33         m1.setxy(12, 15);
34         m2.setxy(22, 25);
35     }

该例子与上面的例子输出相同的结果,只是调用时的参数不一样。

3.this指针

  this指针是一个隐含于每一个类的成员函数中的特殊指针,它用于指向正在被成员函数操作的对象。实际过程是,当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针。/**难怪:在成员函数之外无法访问数据成员,找不到对象呀!(当然中间的private,protected另作谈论**/

当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员时,由隐含作用this指针。而通常不去显式地使用this指针来引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。

 1 #include <iostream.h>
 2     class A
 3     {
 4     public:
 5     A() { a=b=0; }
 6     A(int i, int j) { a=i; b=j; }
 7     void copy(A &aa);    //对象引用作函数参数
 8     void print() {cout<<a<<","<<b<<endl; }
 9     private:
10     int a, b;
11     };
12
13     void A::copy(A &aa)
14     {
15     if (this == &aa) return;    //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址
16     *this = aa;    //*this是操作该成员函数的对象,在这里是对象a1。
17             //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员
18     }
19
20     void main()
21     {
22     A a1, a2(3, 4);
23     a1.copy(a2);
24     a1.print();
25     }

  版权所有,转载请注明转载地址:http://www.cnblogs.com/lihuidashen/p/4383038.html

时间: 2024-12-09 04:30:58

类和对象的使用之对象指针的相关文章

【C++】C++问题——类模板分离编译、函数对象、智能指针

C++类模板的分离编译 过去很多类模板都是整个类连同实现都放在一个头文件里,像STL库就是遵循这样的策略来实现类模板的.现在的标准正试图矫正这种局面. 在实现中又许多函数模板.这意味着每个函数都必须包含模板声明,并且在使用作用域操作符的时候,类的名称必须通过模板变量来实例化. 比如一个operator=的代码: template <typename Object> const MemoryCell <Object> & MemoryCell<Object>::o

黑马程序员---OC基础2【对象储存】【函数和方法的区别】【方法和对象关系】【对象作为方法参数】【NSString类介绍】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- [对象储存] 1.对象的储存细节 [Car  new] new做了3件事 1)向计算机申请存储空间 2)给类中的每一个成员初始化值 3)返回新申请的空间的首地址 (1).申请的空间在内存的哪个区? new 的时候申请的空间内存的堆区(程序动态分配的内存空间) 当new内存的布局: 初始化的时候: 如果实例变量是基本数据类型,此时给初始为0, 如果是字符串类型此时初始化为null (2).实例变

C++ Primer 学习笔记_23_类与数据抽象(9)--四种对象生存期和作用域、static 用法总结

C++ Primer 学习笔记_23_类与数据抽象(9)--四种对象生存期和作用域.static 用法总结 前言: 从上图可知,程序占用的内存被分了以下几部分. (1).栈区(stack) 存放函数的参数值,局部变量的值等,内存的分配是连续的.栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自动被销毁,其特点是效率高,但空间大小有限 注意:通常栈空间容量比较小,一般是1MB-2MB,所以体积比较大的对象不适合在栈中分配. (2).堆区(heap) 由malloc系列函数或new操作符

类中属性返回形式(对象,关联数组,索引数组)

class A { public $x, $y; function __construct($x, $y)  { $this->x = $x; $this->y = $y; } function get_value($arr = true)  { if($arr == 'arr')   { // 类中属性以关联数组形式转换返回 return get_object_vars($this); }else if($arr == 'obj')   { //类中属性以对象形式返回 return $thi

类的序列化和反序列化、对象的归档个解档

对象的编码把对象的类特征以及对象状态转化为某种格式(二进制),这种格式可以存储,也可以在进程间和网络间传递. 类的类型以及实例数据会被写入到某种字节流中,当程序结束的时候,该字节流可以进行持久化.程序启动的时候,新分配的对象可以解码之前保存的自身描述,然后把自己恢复到之前运行时的状态.编码通常需要和归档协作.归档将对象转化成一种可以写进文件系统的格式(档案).解档则是在档案上执行操作.在此过程中,保存在档案的对象需要对自身进行解码. 所以,如果需要将某种类型的实例对象进行归结档,则首先需要对该类

python里的类与一切事物都是对象

对于python,一切事物都是对象,对象基于类创建 列如 name='csdcs' li=[1,3,43] 上面两个都是对象,因为它们都是python中的 类里面存着许多的功能,功能的集合,     对象里存着具体输入的值,与类的内存地址 当对象要进行操作实现不同的功能时,它就会根据保存的内存地址去寻找类引用里面的功能 这样,避免了,功能相同的对象里面,每个对象都去保存相同的功能,它们功能相同都直接去引用类里的功能就行了,类里面就保存了它们的功能 所以对象都是基于类创建的 列如: ll=[11,

Objective-C 【多个对象内存管理(野指针&amp;内存泄漏)】

------------------------------------------- 多个对象内存管理(野指针&内存泄漏) (注:这一部分知识请结合"单个对象内存管理"去理解) 这一部分的知识比较简单,就牵扯到一个会产生野指针的情形和如何避免内存泄漏问题. 代码: #import <Foundation/Foundation.h> @interface Car : NSObject -(void)run; @end @implementation Car //监控

C++ Daily 《6》---- 类静态对象与函数静态对象

C++ 的一个哲学基础是,你不应该为你使用的东西付出代价. class 拥有一个 static 成员,即使从未被用到,它也会被构造和析构: 而 函数拥有一个 static 成员, 如果这个函数从未被调用,则这个对象不会被构造. 做个简单的实验: 结果是没有调用构造函数,因为 thePrinter函数并没有被调用. 相反,类中的一个static 成员,一定会被构造, 因为类的static 成员独立于对象而存在,因此无论是否定义了这个类的对象, static 成员都会构造出来. C++ Daily

[javase学习笔记]-6.5 类类型參数与匿名对象

这一节我们来说说类类型參数和匿名对象. 我们继续用之前的小汽车类吧 class Car { int num;//这是轮胎数属性 String color;//这是颜色属性 String brand;//这是品牌性 void start()//启动行为 { System.out.println("小汽车已启动"); } void run()//这就是执行行为 { System.out.println(num+"..."+color+"..."+br