C++共用数据的保护(const的使用)

共享数据的保护

对于既需要共享、又需要防止改变的数据应该声明为常类型(用 const 进行修饰)

1、const 对象
(1)const 对象的一般形式
类型名 const 对象名[(构造实参表列)];
const 类型名 对象名[(构造实参表列)];
注意:常对象必须要有初值(因为以后不能改值了)。
(2)限定作用:
定义为const的对象的所有数据成员的值都不能被修改。
凡出现调用非const的成员函数,将出现编译错误。但构造函数除外。

Time const t1(12,34,46); // t1是常对象
t1.set_Time(); // 编译错误PE, 非const成员函数
t2.show_Time(); // 错误,非const成员函数

(3) mutable成员
对数据成员声明为mutable(易变的)时,即使是const对象,仍然可以修改该数据成员值。

2、常对象成员
(1) 常数据成员
使用const说明的数据成员称为常数据成员,其值是不能改变的。

如果在一个类中说明了常数据成员,那么构造函数就只能通过初始化列表对该数据成员进行初始化,而任何其他函数都不能对该成员赋值。

class Time
{
    const int hour; // 声明hour为常数据成员
    Time(int h):hour(h){} // 通过参数初始化表对常数据成员hour初始化
};
class Time
{
    const int hour; // 声明hour为常数据成员
    Time(int h)
    {
        hour = h; // 错误
    }
};

常数据成员的举例

#include <iostream.h>
class Date {
public:
    Date(int y,int m,int d);
    void showDate();
    const int &r;
private:
    const int year;
    const int month;
    const int day;
};
Date::Date(int y,int m,int d):year(y),month(m),day(d),r(year){ }
inline void Date::showDate()
{
    cout<<"r="<<r<<endl;
    cout<<year<<"."<<month<<"."<<day<<endl;
}
void main()
{
    Date date1(1998,4,28);
    date1.showDate();
}

(2)常成员函数
~语法形式:返回值类型 函数名(参数表)const { 函数体 }
~关键字 const 在函数原型和函数定义中都要说明,即在函数原型和函数定义的形参列表后加关键字 const
~常对象只能调用常成员函数,且不改变对象的数据成员
~将构造函数和析构函数声明为 const 是编译错误
~在类中使用关键字const说明的函数为常成员函数。

#include<iostream>
using namespace std;
 
class A {
public:
	A(int i) : a(i) { }
	void printA();
private:
	const int a;
	static const int b;		//静态常数据成员
};
class R {
public:
	R(int r1, int r2) : x(r1), y(r2) { }
	void print();
	void print() const;    //const也是区分重载函数的一个因素
private:
	int x, y;
};
 
const int A::b = 10;
void A::printA() {
	cout << a << ":" << b << endl;
}
void R::print() {
	cout << x << ":" << y << endl;
}
void R::print() const 
{    //显式的标出const,编译器才会认真审查函数是否改变对象状态 
	cout << x << ":" << y << endl;
}
 
int main() {
	//常数据成员 
	A c(16);
	c.printA();
	cout << endl;
	//常成员函数 
	R a(5, 4);
	a.print();    //调用void print();若没有定义该函数,对象a调用常函数。普通对象可以调用常函数 
	const R b(20, 52);    //定义的常对象只能用常函数处理;不是常函数,不能通过常对象调用 
	b.print();    //调用void print() const
	return 0;
}
 
结果:
16:10
 
5:4
20:52 
void show_Time( ) const; // 注意const的位置在函数名和括号之后
void Time::show_Time const
{
    cout << hour << minute << sec << endl;
}

注意: const是函数类型的一个组成部分,在声明函数和定义函数时都要有const关键字,在调用时不必加const。

常引用作函数形参
在C++中,经常用常指针和常引用作函数参数。这样既能保证数据安全,使数据不能被随意修改,在调用函数时又不必建立实参的拷贝,可以提高程序运行效率。

class Time{
public:
    Time(int,int,int);
    int hour;
    int minute;
    int sec;
};
Time::Time(int h,int m,int s)
{
    hour = h;
    minute = m;
    sec = s;
}
void fun1(Time &t) // t 是对象引用
{ t.hour = 18; }
void fun2(const Time &t) // t 为常引用
{ t.hour = 18; // 错误 }
int main( )
{
    void fun1(&);
    void fun2(const Time &);
    Time t1(10,13,56);
    fun(t1);
    cout<<t1.hour<<endl;
    return 0;
}

非常对象和常对象的比较

#include<iostream.h>
class Sample {
public:
    int m;
    Sample(int i,int j){ m=i; n=j;}
    void setvalue(int i){ n=i; }
    void disply()
    {
        cout<<"m="<<m<<endl;
        cout<<"n="<<n<<endl;
    }
private:
    int n;
};
void main()
{
    Sample a(10,20); //若为:const Sample a(10,20);
    a.setvalue(40);//不能修改常对象的数据成员
    a.m=30; //不能修改常对象的数据成员
    a.disply();//常对象不能调用普通成员函数
}

#include<iostream.h>
int add(const int& i,const int& j);
void main()
{
    int a=20;
    int b=30;
    cout<<a<<"+"<<b<<"="<<add(a,b)<<endl;
}
int add(const int& i,const& j)
{
    return i+j;
}

(3) 常引用

如果在声明引用时用const修饰,被声明的引用就是常引用。
  常引用所引用的对象不能被更新。
  如果用常引用做形参,便不会意外地发生对实参的更改。常引用的声明形式如下:
  const 类型说明符 &引用名;

 1 //常引用作形参
 2 
 3 #include <iostream>
 5 #include <cmath>
 7 using namespace std;
 9 class Point { //Point类定义
11 public:          //外部接口
13        Point(int x = 0, int y = 0)
15     : x(x), y(y) { 
17        int getX() { return x; }
19        int getY() { return y; }
21        friend float dist(const Point &p1,const Point &p2);
23 private:         //私有数据成员
25        int x, y;
27 };
31 float dist(const Point &p1, const Point &p2)
{ 
33        double x = p1.x - p2.x; 
35        double y = p1.y - p2.y;
37        return static_cast<float>(sqrt(x*x+y*y));
38 
 }
43 int main() 
{  //主函数
44 
45        const Point myp1(1, 1), myp2(4, 5);    
47        cout << "The distance is: ";
49        cout << dist(myp1, myp2) << endl;
51        return 0;
53 }

如果将一个对象说明常对象,则通过该对象只能调用它的常成员函数,而不能调用普通成员函数。而且常成员函数也不能更新对象的数据成员。

常成员函数的使用。

#include <iostream.h>
class Date {
public:
    Date(int y,int m,int d);
    void showDate();
    void showDate() const;
private:
    int year;
    int month;
    int day;
};
Date::Date(int y,int m,int d):year(y),month(m),day(d){ }
void Date::showDate()
{
    cout<<"ShowDate1:"<<endl;
    cout<<year<<"."<<month<<"."<<day<<endl;
}
void Date::showDate() const
{
    cout<<"ShowDate2:"<<endl;
    cout<<year<<"."<<month<<"."<<day<<endl;
}
void main()
{
    Date date1(1998,4,28);
    date1.showDate();
    const Date date2(2002,11,14);
    date2.showDate();
}

常成员函数只能引用本类中的数据成员,而不能修改它们,即成员数据不能作为语句的左值。
(注意:可以改mutable成员)
常成员的使用

a) 如果在一个类中,有些数据成员的值允许改变,另一些数据成员的值不允许改变,则可以将一部分数据成员声明为const,以保证其值不被改变,可以用非const的成员函数引用这些数据成员的值,并修改非const数据成员的值。
b) 如果要求所有的数据成员的值都不允许改变,则可以将所有的数据成员声明为const,或将对象声明为const(常对象),然后用const成员函数引用数据成员,这样起到“双保险”的作用,切实保证了数据成员不被修改。
c) 如果已定义了一个常对象,则只能调用其中的const成员函数,而不能调用非const成员函数(不论这些函数是否会修改对象中的数据)。如果需要访问对象中的数据成员,可将常对象中所有成员函数都声明为const成员函数,但应确保在函数中不修改对象中的数据成员。

(3)共享数据
我们知道类的成员可以划分为公共成员、私有成员、保护成员和不可访问成员。
公有成员,类内外都可以直接访问。
私有成员、保护成员,只有类内可以直接访问。
不可访问成员由继承而来,类内外都不可以直接访问
所以有人把类形容成一个黑箱,外部只能通过各个接口使用类
通过类的数据隐藏保证了数据的安全性,但也有一些形式的数据共享可以破坏这种数据的安全性。
1)类的友元
类的封装不是绝对的,通过友元关系可以访问封装于另一个类里的成员。友元函数,使类外定义的函数可以访问类内的所有成员;

友元函数
使类外定义的函数可以访问类内的所有成员

#include<iostream>
using namespace std;
class A
{
private:
	int a;
public:
	A()
	{
		a=1;
	}
friend void show(A &m);//声明show函数为A类的友元函数
};
void show(A &m)//友元函数可以直接访问A类对象的私有成员
{
	cout<<m.a<<endl;
}
int main()
{
	A m;
	show(m);
}

友元类
若A类为B类的友元类,则A类可以直接访问B类的对象里的所有成员;

#include<iostream>
using namespace std;
class A{
private:
	int a;
public:
	A(){         //A的构造函数
		cout<<"A的构造函数"<<endl;
		a=1;
	}
	~A(){        //A的析构函数
		cout<<"A a="<<a<<endl;
	}
	friend class B;     //B是A的友元类
};
class B{
public:
	B(A &n){ //B的构造函数,可以直接访问A类的对象n的所有成员
		cout<<"B begin a="<<n.a<<endl;
		n.a=2;
	}
};
 
int main()
{
	A n;
	B m(n);
}  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值