C++中对象、引用、指针

C++中对象和java中对象不一样,java中对象都是引用类型。例如

 1 public static void main(String[] args) {
 2         Student stu = new Student(); // 创建一个Student对象
 3         stu.setName("zhangsan"); // 设置名字为‘张三’
 4         stu.setAge(18); // 设置年龄为18
 5 
 6         // 打印姓名和年龄
 7         System.out.println("name = " + stu.getName());
 8         System.out.println("age = " + stu.getAge());
 9 
10         handleStudent(stu); // 调用修改学生的姓名年龄的方法
11 
12         System.out.println("调用处理方法之后:");
13         // 打印姓名和年龄,发现数据已经发生变化
14         System.out.println("name = " + stu.getName()); // 打印修改之后的名字
15         System.out.println("age = " + stu.getAge()); // 打印修改之后的年龄
16     }
17 
18     /**
19      * 对学生的姓名年龄做修改
20      * 
21      * @param stu
22      */
23     public static void handleStudent(Student stu) {
24         stu.setName("lisi");
25         stu.setAge(20);
26     }
27 
28     /**
29      * 学生类
30      * 
31      * @author Baoyz
32      * 
33      */
34     static class Student {
35         private String name;
36         private int age;
37 
38         public String getName() {
39             return name;
40         }
41 
42         public void setName(String name) {
43             this.name = name;
44         }
45 
46         public int getAge() {
47             return age;
48         }
49 
50         public void setAge(int age) {
51             this.age = age;
52         }
53 
54     }

输出结果:

  name = zhangsan
  age = 18
  调用处理方法之后:
  name = lisi
  age = 20

 一个方法接收一个对象,调用方法传入的对象是这个对象的引用,也就是方法中操作的对象和传入的是同一个地址的同一个对象。在方法中对改对象作出的操作都会直接影响传入的对象。

 而在C++中并不是这样,例如

 1 // 学生类
 2 class Student
 3 {
 4 private:
 5     string name;
 6     int age;
 7 public:
 8     void setName(string);
 9     void setAge(int);
10     string getName();
11     int getAge();
12 };
13 
14 void handleStudent(Student);
15 
16 int main()
17 {
18     Student stu;    // 创建学生对象
19     stu.setAge(18);    // 设置年龄
20     stu.setName("zhangsan");    // 设置姓名
21 
22     // 打印姓名和年龄
23     cout << "name = " << stu.getName() << endl;
24     cout << "age = " << stu.getAge() << endl;
25 
26     handleStudent(stu);    // 调用修改学生的姓名年龄的方法
27 
28     cout << "调用处理方法之后:" << endl;
29     // 打印姓名和年龄,发现数据并没有变化
30     cout << "name = " << stu.getName() << endl;
31     cout << "age = " << stu.getAge() << endl;
32 
33 }
34 
35 // 对学生的姓名年龄做修改
36 void handleStudent(Student stu)
37 {
38     stu.setAge(20);
39     stu.setName("lisi");
40 }
41 
42 void Student::setName(string name)
43 {
44     this->name = name;
45 }
46 
47 void Student::setAge(int age)
48 {
49     this->age = age;
50 }
51 
52 string Student::getName()
53 {
54     return this->name;
55 }
56 
57 int Student::getAge()
58 {
59     return this->age;
60 }

运行结果:

  name = zhangsan
  age = 18
  调用处理方法之后:
  name = zhangsan
  age = 18

C++中,把一个对象传入一个方法(函数),相当于把这个对象原封不动的复制了一份给形参,操作的并不是同一个对象。

在C++中还有两个容易混乱的概念 引用和指针。

引用类型,声明时候必须要初始化,相当于给变量起了一个别名。例如

int i = 10;    // 创建一个变量i并赋值10
    int &j = i;    // 创建一个引用类型变量j,并初始化,相当于给i起了一个别名叫做j,i和j是同一个数据的两个名字

    cout << "i = " << i << endl;    // 输出10
    cout << "j = " << j << endl;    // 输出10

    i = 20;    // 更改i的值为20

    cout << "i = " << i << endl;    // 输出20
    cout << "j = " << j << endl;    // 输出20

    j = 50;    // 更改j的值为50

    cout << "i = " << i << endl;    // 输出50
    cout << "j = " << j << endl;    // 输出50

引用类型和被引用的变量的数据是同一个,只不过这个数据有两个名字。
既然引用类型可以起别名,最终的数据还是同一个,我们可以把方法的形参声明为引用类型,还是上面学生的例子。看看什么效果

 

 1 // 学生类
 2 class Student
 3 {
 4 private:
 5     string name;
 6     int age;
 7 public:
 8     void setName(string);
 9     void setAge(int);
10     string getName();
11     int getAge();
12 };
13 
14 void handleStudent(Student &);    // 更改为引用类型
15 
16 int main()
17 {
18     Student stu;    // 创建学生对象
19     stu.setAge(18);    // 设置年龄
20     stu.setName("zhangsan");    // 设置姓名
21 
22     // 打印姓名和年龄
23     cout << "name = " << stu.getName() << endl;
24     cout << "age = " << stu.getAge() << endl;
25 
26     handleStudent(stu);    // 调用修改学生的姓名年龄的方法,参数是引用类型
27 
28     cout << "调用处理方法之后:" << endl;
29     // 打印姓名和年龄,发现数据变化,因为处理方法中形参是引用类型,操作的是同一个数据
30     cout << "name = " << stu.getName() << endl;
31     cout << "age = " << stu.getAge() << endl;
32 }
33 
34 // 对学生的姓名年龄做修改,形参是引用类型
35 void handleStudent(Student & stu)
36 {
37     stu.setAge(20);
38     stu.setName("lisi");
39 }
40 
41 void Student::setName(string name)
42 {
43     this->name = name;
44 }
45 
46 void Student::setAge(int age)
47 {
48     this->age = age;
49 }
50 
51 string Student::getName()
52 {
53     return this->name;
54 }
55 
56 int Student::getAge()
57 {
58     return this->age;
59 }

运行结果:

  name = zhangsan
  age = 18
  调用处理方法之后:
  name = lisi
  age = 20

发现调用方法之后,原来对象的数据也发现了变化,说明方法中操作的对象和传入的对象是同一个。

引用类型,引用类型其实和int,char是一样的,int存放的是整数,char存放的是字符,引用类型存放的是地址,只不过因为一个符号“*”搞乱了很多人。

看一个例子

    int i = 10;    // 定义一个int变量i,并赋值,由于int类型存放的是整数,所以可以赋值一个整数10
    int* j = &i;    // 定义一个int指针变量j,由于指针类型存放的是地址,所以赋值一个地址&i,‘&’是取地址符号,&i就是i的地址

    // 我们要把int* j = &i; 中的"int*"看做一个整体,是一种类型

    cout << "整型变量i = " << i << endl;    // 输出 “整型变量i = 10”
    cout << "整型指针变量j = " << j << endl;    // 输出 “整型指针变量j = 0035FA5C”

“int*” 是一种类型,“int”是一种类型,例子中int i 的值是10,int* j 的值是0035FA5C,这是个内存地址。

然后介绍一个操作符“*”,这个“*”和int*中的是不一样的,不要混淆,int*是一个类型,是一东西,不是两个东西。单独一个“*”是一个操作符。

我把“*”叫做 取值符,与“&”取址符对应。“*”的后面是地址,意思是取地址上面的值;“&”后面是变量,意思是取变量数据的地址。

    int i = 10;    // 定义一个int变量并赋值10
    int* j;    // 定义一个int指针类型
    j = &i;    // 使用取址符,获取int i的地址,将地址赋值给int* j
    // 通过&i得到i的地址,把这个地址赋值给j,j里面存放了一个地址
    int k = *j;    // 使用取值符,获取j中地址上面的值,由于j是int指针类型,存放的地址上面的数据必须是是int类型,将获取的数据赋值给int k
    
    cout << "从指针j存放的地址上面取到的值是:k = " << k << endl;    // 打印k为10

一个指针变量,只是单纯存放了一个地址(就是一串数字编号),并无特别之处。只是我们可以通过“*”取值符获取改指针变量存放地址上面的数据。有了这个概念,我们在看看上面学生的例子。

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 // 学生类
 7 class Student
 8 {
 9 private:
10     string name;
11     int age;
12 public:
13     void setName(string);
14     void setAge(int);
15     string getName();
16     int getAge();
17 };
18 
19 void handleStudent(Student *);    // 更改为指针类型
20 
21 int main()
22 {
23     Student stu;    // 创建学生对象
24     stu.setAge(18);    // 设置年龄
25     stu.setName("zhangsan");    // 设置姓名
26 
27     // 打印姓名和年龄
28     cout << "name = " << stu.getName() << endl;
29     cout << "age = " << stu.getAge() << endl;
30 
31     // handleStudent(stu);    // 这样写是错的,参数是指针类型存放的是地址,要传入一个地址不是对象
32     handleStudent(&stu);    // 通过“&”取址符获取对象的地址传入该方法
33 
34     cout << "调用处理方法之后:" << endl;
35     // 打印姓名和年龄,发现数据变化,因为处理方法中形参是引用类型,通过“*”获取该地址上面的数据(对象)进行操作,与原对象是同一个
36     cout << "name = " << stu.getName() << endl;
37     cout << "age = " << stu.getAge() << endl;
38 
39 }
40 
41 // 对学生的姓名年龄做修改,形参是指针类型
42 void handleStudent(Student * stu)
43 {
44     // stu.setAge(20);    // 这样写是错误的,因为指针类型是地址不是对象,需要“*”取值符来得到地址上面的对象
45     // stu.setName("lisi");
46     (*stu).setAge(20);    // 修改指针stu存放地址上面对象的age
47     (*stu).setName("lisi");    // 修改指针stu存放地址上面对象的name
48 }
49 
50 void Student::setName(string name)
51 {
52     this->name = name;
53 }
54 
55 void Student::setAge(int age)
56 {
57     this->age = age;
58 }
59 
60 string Student::getName()
61 {
62     return this->name;
63 }
64 
65 int Student::getAge()
66 {
67     return this->age;
68 }

运行结果:

  name = zhangsan
  age = 18
  调用处理方法之后:
  name = lisi
  age = 20

posted @ 2013-07-18 17:59  Android Coder  阅读(401)  评论(0编辑  收藏  举报