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