一、const
安全
0.const作用:
1.可以用来修饰变量,修饰函数参数,修饰函数返回值,且被const修饰的东西,都受到强制保护,可以预防其他代码无意识的进行修改,从而提高程序的健壮性
2.使编译器保护那些不希望被修改的参数,防止无意代码的修改
3.增强代码的可读性
1.修饰成员变量-----const变量(常成员变量)(不能被修改)
//注意初始化
方法1:直接给值
const int val=10;
方法2:通过构造函数 初始化列表进行初始化
A(int x=0):val(x){
}
调用时:
A a1(34);---->val值就固定在34;
eg:初始化
class A
{
private:
//const int val = 10; // 方法1 : 对const变量 直接给值
const int val;
int i;
public:
A(int x=0): val(x) { // 方法2: 通过构造函数 初始化列表进行初始化
//val = x;
}
};
int main(void)
{
A a1(34);
a1.print_val();
return 0;
}
2.修饰成员函数----const函数(常成员函数)
函数不能修改成员变量
注意const放在最后面
eg:void print_val(void) const;
本质是修饰的this指针
注:1.构造函数非常特殊,不能修饰为常成员函数
2.修改了变量的函数,不能设置为常成员函数
class A
{
private:
int val;
public:
A(int x=0): val(x) //构造函数 非常特殊 不能修饰为 常成员函数
{
}
void set_val(int x) //由于修改了val,不能被设置成常成员函数
{
val = x;
}
void print_val(void) const //常成员函数,不修成员变量的函数 都应该被设置成常成员函数
{
cout<<"val:"<<val<<endl;
}
};
int main(void)
{
A a1(34);
a1.print_val();
return 0;
}
3.修饰对象 -----类似于C中修饰变量
整个对象都是只读,不能修改,
只能调用常成员函数,不能调用普通函数,(普通函数可能涉及修改变量)
只能读常成员变量,不能修改值
int main(void)
{
const A a1(34); //const对象, a1对象不能被修改
//a1.set_val(234); //不能调函数修改
//a1.i = 35; //不能直接修改
a1.print_val(); //只能调用常成员函数 不能调用普通函数
cout<<a1.i; //只能读 不能修改
return 0;
}
二、static
效率
static修饰成员:
意义:提高效率,同时也可以实现简单的对象间通信(类似于同通信间的管道)
ststic修饰的变量,会储存在静态储存区,普通的局部变量在栈区
1.修饰成员变量 —static变量(静态变量)
tstic修饰的变量,会储存在静态储存区,这些变量在整个程序运行过程中都存在(区分全局变量)
普通的局部变量在栈区,随着所在的函数调用和退出而分配和销毁
静态变量,不属于哪一个对象,所有对象共同拥有:
不同对象的普通变量没有联系,但静态变量是同一个静态变量
被修饰为static的变量,可以不用通过对象进行访问,eg:A::i;
注:初始化变量应该在外部注释: eg:int A :: num=0;
static不能在类中定义时初始化
class A
{
private:
int val;
public:
static int x;
int i;
A(int x=0): val(x)
{
}
void set_val(int x)
{
this->val = x;
}
void print_val(void) const
{
cout<<"val:"<<this->val<<endl;
}
};
int main(void)
{
A a1;
A a2;
A a3;
//cout<<sizeof(a1)<<endl; //静态变量,不属于哪一个对象,所有对象共同拥有。
a1.x = 100;
cout<<a2.x<<endl;
cout<<&a1.x<<","<<&a3.x<<endl;
cout<<A::x<<endl; //静态变量,可以不用通过定义对象来访问
return 0;
}
2.修饰成员函数----static函数(静态方法)
被修饰为static的函数,可以不用通过对象进行调用,eg:A::fun();
静态方法 不拥有this指针,不能直接访问非静态成员
对于通过静态方法访问非静态变量:
在C++中,静态函数是属于类的,而不是对象的。
静态函数没有隐式的this指针,因此无法直接访问类的非静态成员。
然而,你可以通过传递对象的引用或指针作为参数来访问类的非静态成员。
另外,如果非静态成员是静态函数的静态变量,那么静态函数是可以访问这些静态变量的。
静态函数只能访问静态成员或者通过参数传递的对象的非静态成员,不能直接访问其他对象的非静态成员。
静态函数是独立于对象的,因此无法使用对象的实例来访问非静态成员。
限制构造中static方法就是用指针访问类中的非静态变量
class A
{
private:
static int x;
int val;
public:
int i;
A(int x=0): val(x)
{
}
void set_val(int x)
{
this->val = x;
}
void print_val(void) const
{
cout<<"val:"<<this->val<<endl;
}
static void fun(void) //静态方法,不拥有this指针
{
cout<<"fun_test"<<endl;
//cout<<i<<endl; //由于静态方法 没有this指针,因此不能访问普通成员函数与普通成员函数
//set_val(124);
cout<<x<<endl;
//可以访问 静态变量,静态方法
}
};
int A::x;
int main(void)
{
//A a1(74);
A::fun();
return 0;
}
三、friend友元
侧重效率,但安全性减低
友元函数:通过friend + 普通函数
如果需要将普通函数声明为某个类的友元函数,只需要在该类中进行友元声明即可,
不管public或private中进行声明都可以
即在类外写函数本体,需要调用类中元素时,提前在类中进行友元函数声明
friend + 普通函数
注意:友元也破坏了类的隐藏和封装,所以必须慎用(牺牲安全,提高效率)
class A
{
private:
int val;
public:
A(int x=0): val(x)
{
}
void set_val(int x)
{
val = x;
}
int get_val(void)
{
return val;
}
void print_val(void) const
{
cout<<"val:"<<val<<endl;
}
friend void fun( A &obj ); //声明 fun函数 为类A 的友元函数
};
//提出了一个需求:设计一个普通函数 访问A中的私有数据
//解决方法: 设计成 友元函数
void fun( A &obj )
{
// int x = obj.get_val();
// cout<<x<<endl;
cout<<obj.val<<endl;
}
int main(void)
{
A a1(78);
//a1.print_val();
fun(a1);
A a2(64);
fun(a2);
return 0;
}