接上一章节继续:第七章丨C++编程宝典:快速上手、深入进阶、挑战高级技巧,助你成为编程达人 – 菜鸟资源 (xiciw.com)
4.15.static const 成员
如果一个类的成员,既要实现共享,又要实现不可改变,那就用 static const 修饰。
修饰成员函数,格式并无二异,修饰数据成员。必段要类内部实始化
class A
{
public:
static const void dis()
{
cout<<i<<endl;
}
private:
const static int i = 100;
};
int main()
{
A::dis();
return 0;
}
4.16.指向类成员的指针
在 C++语言中,可以定义一个指针,使其指向类成员或成员函数,然后通过指针
来访问类的成员。这包括指向属性成员的指针和指向成员函数的指针。
4.16.1. 指向普通变量和函数的指针
#include <iostream>
using namespace std;
void func(int a)
{
cout<<a<<endl;
}
int main()
{
int a = 100;
int *p = &a;
cout<<*p<<endl;
void (*pf)(int) = func;
pf(10);
return 0;
}
4.16.2. 指向类数据成员的指针
定义
<数据类型><类名>::*<指针名>
赋值&初始化
<数据类型><类名>::*<指针名>[=&<类名>::<非静态数据成员>]
指向非静态数据成员的指针在定义时必须和类相关联,在使用时必须和具体的对象关联。
解用引
由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定类的一个对象,然后,通过对象来引用指针所指向的成员。
<类对象名>.*<指向非静态数据成员的指针>
<类对象指针>->*<指向非静态数据成员的指针>
案例
#include <iostream>
using namespace std;
class Student
{
public:
Student(string n, int nu):name(n),num(nu){}
string name;
int num;
};
int main()
{
Student s("zhangsan",1002);
Student s2("lisi",1001);
// string *ps = &s.name;
// cout<< *ps<<endl;
string Student::*ps = &Student::name;
cout<<s.*ps<<endl;
cout<<s2.*ps<<endl;
Student *pp = new Student("wangwu",1003);
cout<<pp->*ps<<endl;
return 0;
}
4.16.3. 指向类成员函数的指针
定义一个指向非静态成员函数的指针必须在三个方面与其指向的成员函数保持一
致:参数列表要相同、返回类型要相同、所属的类型要相同
定义
<数据类型>(<类名>::*<指针名>)(<参数列表>)
赋值&初始化
<数据类型>(<类名>::*<指针名>)(<参数列表>)[=&<类名>::<非静态成员函数>]
解用引
由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定类的一个对象,然后,通过对象来引用指针所指向的成员。
(<类对象名>.*<指向非静态成员函数的指针>)(<参数列表>)
(<类对象指针>->*<指向非静态成员函数的指针>)(<参数列表>)
案例
#include <iostream>
using namespace std;
class Student
{
public:
Student(string n, int nu):name(n),num(nu){}
void dis()
{
cout<<"name "<<name<<" num "<<num<<endl;
}
private:
string name;
int num;
};
int main()
{
Student s("zhangsan",1002);
Student s2("lisi",1001);
Student *ps = new Student("lisi",1003);
void (Student::*pf)() = & Student::dis;
(s.*pf)();
(s2.*pf)();
(ps->*pf)();
return 0;
}
小结:
与普通意义上的指针不一样。存放的是偏移量。
指向非静态成员函数时,必须用类名作限定符,使用时则必须用类的实例作限定符。
指向静态成员函数时,则不需要使用类名作限定符。
4.16.4. 应用提高
用指向类员函数的指针,实现更加隐蔽的接口。
#include <iostream>
using namespace std;
class Widget
{
public:
Widget()
{
fptr[0] = &f;
fptr[1] = &g;
fptr[2] = &h;
fptr[3] = &i;
}
void select(int idx, int val)
{
if(idx<0 || idx>cnt) return;
(this->*fptr[idx])(val);
}
int count()
{
return cnt;
}
private:
void f(int val){cout<<"void f() "<<val<<endl;}
void g(int val){cout<<"void g() "<<val<<endl;}
void h(int val){cout<<"void h() "<<val<<endl;}
void i(int val){cout<<"void i() "<<val<<endl;}
enum{ cnt = 4};
void (Widget::*fptr[cnt])(int);
};
int main()
{
Widget w;
for(int i=0; i<w.count(); i++)
{
w.select(i,1);
}
return 0;
}
4.16.5. 指向类静态成员的指针
指向类静态数据成员的指针
指向静态数据成员的指针的定义和使用与普通指针相同,在定义时无须和类相关联,在使用时也无须和具体的对象相关联。
指向类静态成员函数的指针
指向静态成员函数的指针和普通指针相同,在定义时无须和类相关联,在使用时也无须和具体的对象相关联。
#include <iostream>
using namespace std;
class A
{
public:
static void dis();
static int data;
};
void A::dis()
{
cout<<data<<endl;
}
int A::data = 100;
int main()
{
int *p = & A::data;
cout<<*p<<endl;
void (*pfunc)() = A::dis;
pfunc();
return 0;
}
4.17.作业
4.17.1. 按需求设计一个圆类
输入圆的半径和圆柱的高,依次输出圆周长、圆面积、圆球表面积、圆柱体积(以空格分隔,π取 3.14)。
4.17.2. 编写C++程序完成以下功能:
1)定义一个 Point 类,其属性包括点的坐标,提供计算两点之间距离的方法;
2)定义一个圆形类,其属性包括圆心和半径;
3)创建两个圆形对象,提示用户输入圆心坐标和半径,判断两个圆是否相交,并输出结果
第四小节完,下一章继续讲解第五小节《5. 友元(Friend)》