C++ 4 引用、指针、常量、静态、友元

C++ 4 引用、指针、常量、静态、友元

引用 &

  • 引用不另开辟内存单元
int a; 
int &b = a;     //b 是 a 的别名,a、b 代表同一变量单元
int &c = b;     //c 是 b 的别名
int *p = &b;    //指针变量 p 指向变量 a 的引用 b ,相当于指向 a
int* &q = p;    //q 为一个指向整型变量的指针变量的引用,初始化为 p

int a = 3;
const int &b = a;
int &b = a;     //错误,未加 const
b = 5;          //错误
a = 5;          //合法

c = &a;         //错误,引用在初始化后不再被重新声明为另一变量的别名
int &c = a;     //错误,引用在初始化后不再被重新声明为另一变量的别名

void &d = 9;    //错误,不能建立 void 类型的引用

int g[5];
int &f[5] = g;  //错误,不能建立引用的数组  
//定义
void swap(int &a, int &b){}   //利用引用形参
void swap(int *a, int *b){}   //利用指针
//void swap(int a, int b)     //i, j 无法实现交换
void fun(Time& T){}           //利用引用形参, T 为别名
void fun(Time* p){}           //利用指针

//调用
swap(i, j);                   //利用引用形参
swap(&i, &j);                 //利用指针
void fun(T);                  //利用引用形参
void fun(p);                  //利用指针

指针 *

① 指向对象的指针

//定义
Student stu, *p;   
p = &stu;

//调用
p->num = 100;
p->data();

(*p).num =100;  //或
(*p).data();

stu.num = 100;    //或
stu.data();

② 指向对象数据成员的指针

//定义
int *p;
p = &stu.name;

//调用
cout<<*p<<endl;

③ 指向对象成员函数的指针

//定义
void(Student::*p)(int, char);
p = &Student::fun

void(Student::*p)(int, char) = &Student::fun;  //合为一行

//调用
(stu.*p)(99, "A");     //即 stu.fun(99, "A");

④ 指向普通函数的指针

//定义
void(*p)(int, char);
p = fun;

//调用
(*p)(99, "A");         //即 fun(99, "A");

⑤ 指向当前对象的 this 指针

  • 每个函数成员中都包含this指针,指向本类的对象
stu.fun();   //stu 的起始地址赋给 this 指针
this->name   //相当于 stu.name
(*this).name

常量 const

  • const——只读
形式含义
const float PI = 3.14;常变量
Student const stu(01, "A");常对象
const Student stu(01, "A");常对象
const int name;常数据成员
void show() const;常成员函数
const int *p;指向对象的常指针
const Student *p;指向常变量的指针变量
const int *p;指向常对象的指针变量
const Student &a = stu;对象的常引用

① 常变量

const float PI = 3.141592653;   //常变量

② 常对象

  • 定义常对象时,必须同时进行初始化,之后不能再改变
  • 只能调用其常成员函数,常成员函数是常对象的唯一对外接口
Student const stu(01, "A");
const Student stu(01, "A");
  • 有时一定要修改常对象中某个数据成员的值 ( 如用于计数的变量count) ,将其声明为mutable
mutable int count;

③ 常对象成员——常数据成员

  • 常数据成员只能通过构造函数的参数初始化表来进行初始化
const int name;

//类内定义
Student(char n):name(n){}

//类外定义
Student(char n);                     //类内声明

Student::Student(char n):name(n){}   //类外定义

④ 常对象成员——常成员函数

  • 只能引用本类的数据成员,且不能修改
  • 不能调用另一个非const成员函数
void show() const;
数据成员const的普通成员函数const成员函数
const的普通数据成员可以引用,也可以改变值可以引用,但不可以改变值
const数据成员可以引用,但不可以改变值可以引用,但不可以改变值
const对象不允许可以引用,但不可以改变值
不能调用另一个非const成员函数

⑤ 指向对象的常指针

  • 指针变量为常量,不能改变指向,指针变量始终指向一个对象
Student stu(01, "A");

//定义
Student * const p;
p = &stu;

Student * const p = &stu;     //或

⑥ 指向常变量的指针变量

  • 指向常变量的指针变量指向非常变量,不能通过该指针来改变其值,,但指针的指向可以改变用该指针访问期间,该变量具有常变量的特征
//定义
int a;
const int *p;
p = &a;

//调用
*p = 1;    //非法,不能通过 p 来改变 a 值
a = 1;     //合法
  • 指向常变量的指针变量指向常变量,且常变量只能用指向常变量的指针指向它,不能通过该指针来改变其值,但指针的指向可以改变
//定义
const int a = 1;
const int *p;
p = &a;

const char b[] = "hello";   //数组
const char *q;
q = b;
  • 若函数的形参是指向非const变量的指针变量,实参只能用指向非const变量的指针
形参实参合法否改变指针所指向的变量的值
指向非const变量的指针const变量的地址合法可以
指向非const变量的指针const变量的地址非法——
指向const变量的指针const变量的地址合法不可以
指向const变量的指针const变量的地址合法不可以

⑦ 指向常对象的指针变量

  • 指向常对象的指针变量指向常对象,不能通过该指针来改变其值,但指针的指向可以改变
//定义
const Student stu(01, "A");
const Student *p;
p = &stu;

const Student *p = &stu;  //或

//调用
(*p).name = "B";    //非法
stu.name = "B";     //非法  
  • 指向常对象的指针变量指向非常对象,不能通过该指针来改变其值,但指针的指向可以改变
//定义
Student stu(01, "A");
const Student *p = &stu;

//调用
(*p).name = "B";    //非法,不能通过 p 来改变值
stu.name = "B";     //合法  

⑧ 对象的常引用

  • 常用常指针和常引用作函数参数,可不必建立实参的拷贝
const Student &a = stu;

静态 static

① 静态数据成员

  • 静态数据成员在内存中只占用一份空间,并不是每个对象都分别为它保存一份空间
  • 静态数据成员对所有对象都是一样的
  • 静态数据成员只能在类体外初始化不能用参数初始化表对其进行初始化,若未初始化,系统自动赋值为 0
//类内定义
static int height;

//类外初始化
int Box::height = 10;

//调用
Box box1;
cout<<Box::height<<endl;   //当 height 被设置为公有才可调用
cout<<box1.height<<endl;

② 静态成员函数

  • 静态成员函数不是为了对象之间的沟通,而是为了处理静态数据成员
  • 静态成员函数不属于某一对象,所以没有this指针,因此不能访问本类中的非静态成员,可以直接引用本类的静态成员
  • 若要访问非静态成员:box1.height
//类内定义
static int fun();

//类外初始化
int Box::fun(){...}

//调用
Box box1;
cout<<Box::fun<<endl;   
cout<<box1.fun<<endl;

友元 friend

① 友元函数

  • 友元函数可以访问这个类中的私有成员
  • 必须作为友元函数的重载运算符函数:<< >> 类型转换运算符
  • 一般将双目运算符重载为友元函数
将普通函数声明为友元函数
  • 其不是类的成员函数,没有this指针,因此在引用私有数据成员时,必须加上对象名
//类内声明
friend void fun()//类外定义
void fun(){}
将另一个类的成员函数声明为友元函数
class Date;  //对 Date 类的提前引用声明
class Time{
    public:
        void display(Date &);  //类内声明
};
class Date{
    public:
        friend void Time::display(Date &);
};

void Time::display(Date &d){}  //类外定义,因为形参为 Date ,所以需在 Date 类定义之后定义函数

② 友元类

  • 友元类可以访问本类所有成员
  • 非双向,若 B 是 A 的友元,不等于 A 是 B 的友元
  • 非传递,若 B 是 A 的友元,C 是 B 的友元,不等于 C 是 A 的友元
// A 类中声明
friend B;

参考资料

  • [1]谭浩强.C++面向对象程序设计(第2版)北京:清华大学出版社,2014.

C++ 1 基础知识
C++ 2 组合与继承
C++ 3 构造函数与析构函数
C++ 4 引用、指针、常量、静态、友元
C++ 5 多态性
C++ 6 输入输出流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值