C++类的特殊成员&&友元函数
1、类的特殊成员
1.1 const 数据成员
- 赋值用初始化表达式的方式进行赋值
- 如果构造函数重载,所有的构造函数对于const成员都要进行初始化
- const成员如果直接使用=赋值,那就可以不用初始化表达式
例一:
class Point
{
private:
int xp;
int yp;
const int zp;
public:
Point(int x,int y,int z):xp(x),yp(y),zp(z)
{
// xp = x;
// yp = y;
// zp = z; // 报错:在这里写是相当于对zp进行赋值
}
Point() {}
void show(void)
{
cout << "xp:" << xp << ",yp:" << yp << ",zp:" << zp << endl;
}
};
int main()
{
Point a(1,2,3);
a.show(); //xp:1,yp:2,zp:3
return 0;
}
例二:
const成员如果直接使用=赋值,那就可以不用初始化表达式
class Point
{
private:
int xp;
int yp;
const int zp = 100;
public:
Point(int x,int y)
{
xp = x;
yp = y;
}
void show(void)
{
cout << "xp:" << xp << ",yp:" << yp << ",zp:" << zp << endl;
}
};
int main()
{
Point a(1,2);
a.show();
return 0;
}
1.2 const 成员的函数
成员函数:
数据类型 函数名(形参) const
{
}
这个函数只能对成员进行读操作,不能对成员进行写操作
如果在这个函数内部只能调用其他const成员函数
例:
class Point
{
private:
int xp;
int yp;
public:
Point(int x,int y):xp(x),yp(y){
}
void test1(void)
{
cout << "无cosnt函数" << endl;
}
void test2(void) const
{
cout << "有const的函数 " << endl;
}
void show(void) const
{
test2();
cout << "xp:" << xp << ",yp:" << yp << endl;
}
};
int main()
{
Point a(3,4);
a.show(); // 有const的函数
// xp:3,yp:4
return 0;
}
1.3 static 数据成员
- static:静态区,程序加载的时候空间就分好了。
- static数据成员在类中所有对象共享,在类外使用:数据类型 类名::静态成员名 = 值;
- static数据成员不能使用this进行操作
例:static数据成员在类中多有对象共享
class Point
{
private:
int xp;
int yp;
static int zp;
public:
Point(int x,int y):xp(x),yp(y){
}
void show(void)
{
cout << "xp:" << xp << ",yp:" << yp << ",zp:" << zp << endl;
}
};
int Point::zp = 100; //初始化
int main()
{
Point a(1,2);
a.show(); // xp:1,yp:2,zp:100
Point b(3,4);
b.show();// xp:3,yp:4,zp:100
return 0;
}
1.4 static 成员函数
- 静态成员:属于类 ,可以使用对象进行调用,也可以使用类直接调用 类名::函数名(实参列表);
- 静态成员函数内只能调用静态成员函数
- 静态成员函数中只能访问静态数据,所以静态成员函数就是为了访问静态成员设计的。
- 不要在用初始化表达式赋值。
例:
class Point
{
private:
int xp;
int yp;
static int zp;
public:
Point(int x,int y):xp(x),yp(y){
}
void test1(void)
{
cout << "无static函数" << endl;
}
static void test2(void)
{
cout << "有static的函数 " << endl;
}
static void show(void)
{
// 调用test1失败
test2();
cout << "show方法,zp:" << zp << endl;
zp = 800
cout << "show方法,zp:" << zp << endl;
}
};
int Point::zp = 500; //初始化
int main()
{
Point a(3,4);
a.show(); //有static的函数
//show方法,zp:500
//show方法,zp:800
Point::show(); //同上
return 0;
}
1.5 引用成员
-
给变量起别名,一般用在传参
-
引用定义的时候必须初始化
类中有引用成员如何赋值?-- 初始化表达式赋值
class Point
{
private:
int xp;
int yp;
int &zp; //定义引用成员
public:
// 错误的初始化因为在构造函数{}内属于赋值不属于初始化
Point(int x,int y,int &z)
{
xp = x;
yp = y;
zp = z;
}
//正确的初始化
Point(int x,int y,int &z):xp(x),yp(y),zp(z)
{
}
void show(void)
{
cout << "xp:" << xp << ",yp:" << yp << ",zp:" << zp << endl;
}
};
1.6 对象成员 – 组合
例如:
人类:头类 身体类 脚类
class Head
{
public:
Head()
{
cout << " ○" << endl;
}
};
class Body
{
public:
Body()
{
cout << " | " << endl;
cout << " |-|" << endl;
}
};
class Foot
{
public:
Foot()
{
cout << " _ _" << endl;
}
};
class Human
{
public:
Head h;
Body b;
Foot f;
Human(Head &h,Body &b,Foot &f)
{
this->h = h;
this->b = b;
this->f = f;
}
};
指针写法
class Human
{
public:
Head *h;
Body *b;
Foot *f;
Human()
{
h = new Head;
b = new Body;
f = new Foot;
}
~Human()
{
delete h;
delete b;
delete f;
}
};
2、友元函数
突破private限制,可以让外部函数访问类内的私有成员。
格式:
返回值类型 函数名(const 类名 &引用名)
{
}
在要访问私有成员的类里面要证明这个函数是这个类的朋友:
格式:
friend 返回值类型 函数名(const 类名 &引用名);
分类:
- 可以外部函数定义为一个类的友元
- 一个类的成员函数定义为另一个类的友元
- 定义 友元类
例一:一个外部函数访问类内的私有成员
class Point
{
private:
int xp;
int yp;
public:
Point(int x,int y):xp(x),yp(y){
}
// 声明printP是Point的朋友
friend void printP(const Point &p1);
};
// 定义一个外部函数想要访问类对象里面的私有成员xp;
void printP(const Point &p1)
{
cout << p1.xp << endl;
}
int main()
{
Point a(1,3);
printP(a); // 1
return 0;
}
例二:
一个B类的成员函数定义为另一个A类的友元函数
1、声明A类型
2、在B类的成员函数要声明和定义分开,定义要在A类的下面
3、在A类型声明友元同时在函数名加 B::
// A找不到 -- 程序顺序问题 -- 声明A类
class A;
class B
{
public:
float distance(A &a,A &b); // 只能声明
};
class A
{
private:
int xp;
int yp;
public:
A(int x,int y):xp(x),yp(y){};
// 声明朋友
friend float B::distance(A &a,A &b);
};
// 在A类的下面定义函数
float B::distance(A &a,A &b)
{
// a.xp a.yp ,....
}
例三:友元 遇到函数重载,只有声明朋友的那个函数才可以访问,没有声明的不行
class Point;
class Line
{
public:
float distance(Point &a,Point &b);
float distance(Point &a);
};
class Point
{
private:
int xp;
int yp;
public:
Point(int x,int y):xp(x),yp(y)
{
}
// 两个都声明才可以用
friend float Line::distance(Point &a,Point &b);
friend float Line::distance(Point &a);
};
float Line::distance(Point &a,Point &b)
{
float d;
d = sqrt((a.xp-b.xp)*(a.xp-b.xp) + (a.yp-b.yp)*(a.yp-b.yp));
return d;
}
float Line::distance(Point &a)
{
cout << "重载distance " << a.xp << endl;
return 1.0;
}
例四:友元类 — 将整个类声明为友元
//接例三
class Point
{
private:
int xp;
int yp;
public:
Point(int x,int y):xp(x),yp(y)
{
}
//friend float Line::distance(Point &a,Point &b);
//friend float Line::distance(Point &a);
friend Line;
};