对于C++中引用和指针的理解

引用:

  • 引用是C++提供的一种数据类型。定义引用类型变量的一般格式为:

    <数据类型> & <引用变量名> = <变量名>;
    //变量名为已定义的变量
  • 我们在程序中定义引用类型变量,实际上是给已定义的变量起一个别名而已,引用类型的变量没有单独的存储空间,而是与其相关联的变量使用同一空间。举个生活中的例子:假如你叫张三,这是你父母给你取的名字。然而,你逗比的朋友李四很喜欢叫你“三哥”。这里的张三就是变量名,三哥就是引用变量名。但无论是张三还是三哥,都是指你本人。

  • 使用:

#include <iostream>
using namespace std;
int main()
{
    int a = 9;
    int &refa = a;
    cout << "a = " << a << " , " << "refa = " << refa << endl;
    refa = 10;
    cout << "a = " << a << " , " << "refa = " << refa << endl;
}
  输出如下:
  a = 9 , refa = 9
  a = 10 , refa = 10

  //从上述例子,我们可以看出,对引用变量的修改实质上是对其相关联的变量的修改,这也进一步说明了这两个变量是共用同一空间的。

指针:

  • 首先,我们来回顾一个简单的例子:
//基本类型当做函数参数
  #include<iostream>
  using namespace std;

  void swap(int x, int y)
  {
    int t;
    t = x;
    x = y;
    y = t;
  }

  int main()
  {
    int x = 3, y = 9;
    swap(x, y);
    cout << "x = " << x << " , y = " << y << endl;
    return 0;
  }

 输出如下:
 x = 3 , y = 9
//指针做函数参数
#include <iostream>
using namespace std;

void swap(int *px, int *py)
{
    int t;
    t = *px;
    *px = *py;
    *py = t;
}

int main()
{
    int x = 3, y = 9;
    swap(&x, &y);
    cout << "x = " << x << " , y = " << y << endl;
    return 0;
}
输出如下:
x = 9, y = 3

对比这两段,我们可以看出:用基本类型量做参数时,无法通过参数带回多个结果。用指针做函数参数时,可以通过参数指针带回多个运算结果,但是指针比较难理解,而且书写通过间接访问变量的语句也比较麻烦。

再来看下引用类型做函数参数的例子:

//引用类型做函数参数
#include <iostream>
using namespace std;

void swap(int &x, int &y)
{
    int t;
    t = x;
    x = y;
    y = t;
}

int main()
{
    int x = 3, y = 9;
    swap(x, y);
    cout << "x = " << x << " , " << "y = " << y << endl;
    return 0;
}
输出如下:
x = 9, y = 3

可以看到,只是在swap()函数形参的定义时,写成了变量引用形式(参数传递是相当于有int &x = x,;int &y = y;),执行效果却和指针做函数参数时一样。可以看到,使用引用参数类型做参数的优点是:

  • 避免了使用指针做参数时的程序书写及理解的麻烦
  • 增强了程序的可读性和编程的方便性,在被调函数中直接写引用变量名,直观且易理解
  • 提高了程序执行的效率,因为系统在执行时不需要为引用参数动态分配存储空间

引用和指针的区别

  • 在声明引用时必须将其初始化,而不能像指针那样,先声明,再赋值
int a;
int &refa;
refa = a;
//上面这种写法是错误的
  • 引用更像是const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就至始至终都效忠于它。
 int a;
 int &refa = a;     //与下面一句等价
 int * const pa = &a;
 //其中,refa就与*pa等价。
  • 来看个例子:
#include <iostream>
using namespace std;
int main()
{
    int a = 10;
    int &refa = a;

    cout << "a = " << a
        << " , refa = " << refa << endl;

    cout << "a address = " << &a
        << " , refa address = " << &refa << endl;

    int b = 20;
    refa = b;       //尝试更改引用变量refa,让其成为b的引用

    cout << "b = " << b
        << " , a = " << a
        << " , refa = " << refa << endl;

    cout << "b address = " << &b
        << " , refa address = " << &refa
        << " , a address = " << &a << endl;

    return 0;
}
输出如下:
a = 10, refa = 10
a address = 0073F804, refa address = 0073F804
b = 20, a = 20, refa = 20
b address = 0073F7EC, refa address = 0073F804, a address = 0073F804

分析:
刚开始,refa引用的是a。接着,我们使用refa = b;这一句,尝试将refa更改为b的引用。但是从输出结果来看,这一句并没有达到我们想要的目的。虽然,refa的值变成了20,但与此同时,a的值也变成了20。而且,refa的地址仍然与a的地址相同,与b的地址不同。这进一步说明,引用只在创建时初始化有效,一旦与某个变量关联起来,就至始至终都效忠于它,即使通过赋值的方式来设置也是无效的。此外,通过赋值来设置的话,只是能改变与引用相关联的变量的内容而已。

  • 再看个例子:
  #include<iostream>
  using namespace std;
  int main()
  {
    int a = 10;
    int *pa = &a;
    int &refa = *pa;
    int b = 20;
    pa = &b;
    cout << "a = " << a
        << " , b = " << b
        << " , refa = " << refa<<endl;

    cout << "a address = " << &a
        << " , pa address = " << pa
        << " , b address = " << &b
        << " , refa address = " << &refa << endl;

    return 0;
  }
 输出结果如下:
 a = 10 , b = 20 , refa = 10
 a address = 00DEFA08 , pa address = 00DEF9E4 , b address = 00DEF9E4 , refa address = 00DEFA08

分析:
这里将refa初始化为*pa,*pa即为a。接下来,更改pa的指向,让其指向变量b。最后,我们再输出各个变量的值,发现refa的值与地址依旧与a相同。这更加证明了上面例子的说法与结论。引用一旦设置成功,就无法再更改指向。这是与普通的指针使用上最大的不同。

  • 最后,看个综合的例子:
#include <iostream>
using namespace std;

void modify_value10(int n);         //参数:值
void modify_value20(int *pn);       //参数:指针
void modify_value30(int &n);        //参数:引用

int main()
{
    int a = 5;
    int *pa = &a;
    int &refa = a;

    cout << "a address = " << &a << endl << endl;
    modify_value10(a);
    cout << "modify_value10(): a = " << a << endl << endl;
    modify_value20(pa);
    cout << "modify_value20(): a = " << a << endl << endl;
    modify_value30(refa);
    cout << "modify_value30(): a = " << a << endl << endl;
}

void modify_value10(int n)
{
    n = 10;
    cout << "n address : " << &n << endl;
}

void modify_value20(int *pn)
{
    *pn = 20;
    cout << "*pn address : " << pn << endl;
}

void modify_value30(int &n)
{
    n = 30;
    cout << "n address : " << &n << endl;
}
输出结果如下:
a address = 010FF9AC

n address : 010FF8C0
modify_value10(): a = 5

*pn address : 010FF9AC
modify_value20(): a = 20

n address : 010FF9AC
modify_value30(): a = 30

分析:这段程序我们分别创建三个函数来更改a变量的值,三个函数分别使用普通变量,指针变量以及引用变量来当做参数。其中,modify_value10()函数在调用时,要为形参另外开辟一个整型大小的空间,该空间首地址为010FF8C0。
modify_value20()函数在调用时,通过间接访问运算符*来访问同变量a同一地址的内存空间,它与modify_value10()虽然同为传值调用,但是它传的是变量的地址值,可以直接操作变量的内容,另外,它没有额外开辟内存空间,效率比较高,但可读性不是很好。
modify_value30()中,n就是变量a的别名,在函数中的操作其实就等价于直接操作变量a了,效率也高,可读性也好。

总结:

在C++中, 增设引用变量其实是为了提高程序的效率以及代码的可阅读性。引用能做的事情,指针都能做。但是在某些场景下,使用指针会给程序带来不安全性。例如:指针为NULL的话(指针的为空性,这里不讨论const),可能会引起程序的一些异常。而这时,你用引用的话,可能能避免这种情况的发生,因为引用在定义时就必须同时进行初始化,不具备为空性。或许,你在定义一个函数时,只想使用传递给它的信息,而不对信息进行修改,同时又想使用引用,则应使用常量引用。可以这样用,double ref_no_modify(const double &ra)。对于指针与引用在函数参数中的使用孰优孰劣,这个就见仁见智了。

指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4 指向类的成员的指针C++,可以说明指向类的数据成员和成员函数指针。 指向数据成员的指针格式如下: ::* 指向成员函数指针格式如下: (::*)() 例如,设有如下一个类A: class A { public: int fun (int b) { return a*c+b; } A(int i) { a=i; } int c; private: int a; }; 定义一个指向类A的数据成员c的指针pc,其格式如下: int A:: *pc = &A::c; 再定义一个指向类A的成员函数fun的指针pfun,其格式如下: int (A:: *pfun)(int) = A::fun; 由于类不是运行存在的对象。因此,在使用这类指针,需要首指定A类的一个对象,然后,通过对象来引用指针所指向的成员。例如,给pc指针所指向的数据成员c赋值8,可以表示如下: A a; a.*pc = 8; 其,运算符.*是用来对指向类成员的指针来操作该类的对象的。 如果使用指向对象的指针来对指向类成员的指针进行操作,使用运算符->*。例如: A *p = &a; //a是类A的一个对象,p是指向对象a的指针。 p ->* pc = 8; 让我们再看看指向一般函数指针的定义格式: *() 关于给指向函数指针赋值的格式如下: = 关于在程序,使用指向函数指针调用函数的格式如下: (*)() 如果是指向类的成员函数指针还应加上相应的对象名和对象成员运算符。 下面给出一个使用指向类成员指针的例子: #include class A { public: A(int i) { a=i; } int fun(int b) { return a*c+b; } int c; private: int a; }; void main() { A x(8); //定义类A的一个对象x int A::*pc; //定义一个指向类数据成员的指针pc pc=&A::c; //给指针pc赋值 x.*pc=3; //用指针方式给类成员c赋值为3 int (A::*pfun)(int); //定义一个指向类成员函数指针pfun pfun=A::fun; //给指针pfun赋值 A *p=&x; //定义一个对象指针p,并赋初值为x cout<*pfun)(5)<<endl; //用对象指针调用指向类成员函数指针pfun指向的函数 } 以上程序定义了好几个指针,虽然它们都是指针,但是所指向的对象是不同的。p是指向类的对象;pc是指向类的数据成员;pfun是指向类的成员函数。因此它们的值也是不相同的。 对象指针和对象引用函数的参数 1. 对象指针函数的参数 使用对象指针作为函数参数要经使用对象作函数参数更普遍一些。因为使用对象指针函数参数有如下两点好处: (1) 实现传址调用。可在被调用函数改变调用函数的参数对象的值,实现函数之间的信息传递。 (2) 使用对象指针实参仅将对象的地址值传给形参,而不进行副本的拷贝,这样可以提高运行效率,减少空开销。 当形参是指向对象指针,调用函数的对应实参应该是某个对象的地址值,一般使用&后加对象名。下面举一例子说明对象指针函数参数。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M *m); void setxy(int i, int j) { x=i; y=j; } void print() { cout<<x<<","<<y<x; y=m->y; } void fun(M m1, M *m2); void main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22,25); } 输出结果为: 5,7 22,25 从输出结果可以看出,当在被调用函数fun,改变了对象的数据成员值[m1.setxy(12, 15)]和指向对象指针的数据成员值[m2->setxy(22, 25)]以后,可以看到只有指向对象指针作参数所指向的对象被改变了,而另一个对象作参数,形参对象值改变了,可实参对象值并没有改变。因此输出上述结果。 2. 对象引用函数参数 在实际,使用对象引用函数参数要比使用对象指针函数更普遍,这是因为使用对象引用函数参数具有用对象指针函数参数的优点,而用对象引用函数参数将更简单,更直接。所以,在C++编程,人们喜欢用对象引用函数参数。现举一例子说明对象引用函数参数的格式。 #include class M { public: M() { x=y=0; } M(int i, int j) { x=i; y=j; } void copy(M &m); void setxy(int i, int j) { x=i; y=j; } void print() {cout<<x<<","<<y<<endl; } private: int x, y; }; void M::copy(M &m) { x=m.x; x=m.y; } void fun(M m1, M &m2;); void main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2;) { m1.setxy(12, 15); m2.setxy(22, 25); } 该例子与上面的例子输出相同的结果,只是调用的参数不一样。 this指针 this指针是一个隐含于每一个成员函数的特殊指针。它是一个指向正在被该成员函数操作的对象,也就是要操作该成员函数的对象。 当对一个对象调用成员函数,编译程序将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员,由隐含作用this指针。而通常不去显式地使用this指针引用数据成员。同样也可以使用*this来标识调用该成员函数的对象。下面举一例子说明this指针的应用。 #include class A { public: A() { a=b=0; } A(int i, int j) { a=i; b=j; } void copy(A &aa;); //对象引用函数参数 void print() {cout<<a<<","<<b<<endl; } private: int a, b; }; void A::copy(A &aa;) { if (this == &aa;) return; //这个this是操作该成员函数的对象的地址,在这里是对象a1的地址 *this = aa; //*this是操作该成员函数的对象,在这里是对象a1。 //此语句是对象aa赋给a1,也就是aa具有的数据成员的值赋给a1的数据成员 } void main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); } 运行结果: 3, 4
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值