欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c/c++面向对象编程之共用数据的保护

程序员文章站 2022-03-26 12:00:23
...

一、常对象

定义常对象的一般形式为

类名 const 对象名(实参表列)
const 类名 对象名(实参表列)

1)常对象必须有初值
2)在所有的场合中,常对象中所有的成员的值都不能被改变,如果希望保证对象数据成员值不能被改变,就可以声明为常对象
3)一个对象被声明为常对象,就不能调用非const型的成员函数(除了系统自动调用的隐式的构造函数和析构函数)

c/c++面向对象编程之共用数据的保护

4)常成员函数可以访问常对象中的数据成员,但仍然不允许修改常对象中数据成员的值。

c/c++面向对象编程之共用数据的保护

二、常对象成员

1 、常数据成员

其作用和用法与一般常变量相似,用关键字const来声明常数据成员。常数据成员的值是不能改变的。只能通过构造函数的参数初始化表对常数据成员进行初始化。
1)在类体中声明常数据成员
const int num;//声明hour为常数据成员
2)在类外定义构造函数
Student::Student(int n,float s):num(n),score(s){} //通过参数初始化表对常数据成员num和score初始化
3)在类体中声明了某一个数据成员为常数据成员后,该类所有对象中的该数据成员的值都是不能改变的,但不同对象中该变量成员的值可以是不同的(分别在初始化时指定)。

2、常成员函数

返回值类型 函数名()const;
const是函数类型的一部分,声明和定义的时候都要有const关键字,调用时不必加const
c/c++面向对象编程之共用数据的保护

1、一个类中,将不想要改变值的成员声明为const,可以用非const的成员函数引用这些数据成员的值 并修改非const数据成员的值
2、如果要求所有的数据成员的值都不允许改变,可以将所有的数据成员都声明为const,或将对象声明为常对象,然后用const成员函数引用数据成员
3、常对象只能调用其中的const成员函数,而不能调用非const成员函数,与这些函数是否会修改对象中的数据无关,如果需要访问对象中的数据成员,可将常对象中所有的成员函数都声明为const成员函数,但要确保不修改对象中的数据成员

还要注意一下三点:
1.不要误认为常对象中的成员函数都是常成员函数,常对象只保证其所有数据成员的值不被修改。
2.如果在常对象中的成员函数未加const声明,则编译系统会把它当最非const成员函数处理。
3.还要注意,常成员函数不能调用另外一个非cosnt成员函数。

3、指向对象的常指针

将指针变量声明为const型,这样指针值始终保持为初值,不能改变
类名 * const 指针变量名;
const 都要有初值;
这样做是要保证一个指针变量始终指向同一个对象

4、指向常对象的指针变量

  1. 指向常变量的指针变量

    const 类型名 * 指针变量名;
    1)常变量只能用指向常变量的指针指向它
    c/c++面向对象编程之共用数据的保护
    2)指向常变量的指针变量还可以指向未被声明为const的变量,但是不能通过此指针变量改变改变量的值。
    c/c++面向对象编程之共用数据的保护
    3)函数的形参是指向非const型变量的指针,实参是指向非const变量的指针,函数执行过程中可以改变形参指针变量所指向的变量(就是实参指针所指向的变量)的值。当形参是指向const型变量的指针,执行过程中不能改变指针变量所指向的变量 的值。
    c/c++面向对象编程之共用数据的保护
    总结:指向常变量的指针变量可以指向const型和非const型的变量,非const型的指针变量只能指向非const型的变量。

    2.指向常对象的指针变量

    1)对象被被声明为常对象,就只能用指向常对象的指针变量指向它。
    2) 一个指向常对象的指针变量指向了一个非const的对象,这个对象是不能通过指针来改变的
    3) 指向常对象的指针最常用于函数的形参,目的是保护形参指针所指向的对象使它在函数执行过程中不被修改
    4) 指向常对象的指针变量,是不能通过它 改变所指向的对象的值的,但是指针变量本身的值是可以改变的

5、对象的常引用

void fun(const Bottle &b);
这样写就不能在函数中改变b的值,就是说不能改变对应实参的值

6、const数据总结

1) Bottle const b1; b1是常对象,任何情况下都不能改变值
2) void Bottle::fun()const; fun是Bottle类的常成员函数,可以引用但不能修改本类中的数据成员
3) Bottle * const p; p是指向Bottle对象的常指针,p的值(所指向的地址)不能改变
4) const Bottle * p;p是指向Bottle类常对象的指针,其指向的类对象的值不能通过指针来改变
5) const Bottle &b = b1;b是Bottle类对象b1的引用,二者指向同一段内 存;但是用别名b不可以改变值。

7、对象的动态建立和释放

1- new Bottle;
这样就会开辟一段内存空间,并在此空间中存放一个Bottle类对象,同时调用构造函数,使对象初始化
此时这个对象是没有名字的,叫做无名对象
2- new运算符会返回一个指向这个新对象的指针的值(所分配的内存空间的起始地址)
Bottle * pb;
pb = new Bottle;
3- 我们可以在执行new时,对新对象初始化
Bottle * pb = new Bottle(12,55);
4- 不再使用new建立的对象时,可以用delete运算符释放
delete pb;
执行delete运算符时,在释放内存空间之前,自动调用析构函数,此后程序不能在使用该对象
5- 如果指针变量先后指向不同的动态对象,要注意指针变量的当前指向,以免删错了对象

8、对象的赋值和复制

1- 对象的赋值
对象名1 = 对象名2;
对象1和对象2必须属于同一个类。
1) 对象的赋值只是对其中的数据成员赋值,而不对成员函数赋值。
原因?成员函数属于类
2) 类的数据成员中不能包含动态分配的数据,否则在赋值时可能出现严重后果(对象的拷贝构造属于位拷贝。就是说,拷贝后,新对象中用于分配堆内存的指针或引用变量和原有的对象具有相同的二进制地址,一旦原对象释放该段内存,新对象将操作无效内存,最终导致程序崩溃。)
2- 对象的复制
类名 对象2(对象1);
Bottle b2(b1);
Bottle b2 = b1;
复制构造函数(拷贝构造函数)
1) 定义形式
Bottle::Bottle(const Bottle& b){
height =b.height;
width = b.width;
}
2) 复制构造函数也是构造函数,它只有一个参数,这个参数必须是本类的对象,且采用对象的引用形式(约定要加const,防止调用过程对象的值被修改)
3) 如果用户自己未定义复制构造函数,编译系统会自动提供一个默认的复制构造函数,作用只是简单的复制类中的每个数据成员
3- 对象的复制和对象的赋值在概念和语法上都不同
赋值是对一个已经存在的对象赋值,所以要先定义。复制是从无到有建立一个新对象,使它和一个已有的对象完全相同
4- 普通构造函数和复制构造函数的区别
1) 形式上
类名(形参表列);
类名(const类名& 对象名);
2) 实参类型不同
系统会根据实参的类型决定调用普通构造函数还是复制构造函数
3) 什么情况下调用
1)普通构造函数在建立对象时被调用
2)复制构造函数在用已有对象复制一个新对象时被调用
程序中需要建立一个对象,并用另一个同类的对象对它初始化。
当函数的参数为类的对象时。
函数的返回值是类对象。

相关标签: const