实例代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class TestInt { //保存0-100之间的一个数字
//定义一个函数指针类型,代表的函数带一个int 形参,没有返回类型的
//typedef void(*tfpoint)(int);
using tfpoint = void(*)(int);
public:
static void mysfunc(int v1){ //静态成员函数
int test;
test = 1;
}
//新的类型转换运算符,能本类类型 转换成一个 函数指针类型
operator tfpoint(){ // const 不是必须加的,所以这里不加
//必须要返回一个函数指针
return mysfunc; //函数地址(函数名) 作为函数指针类型返回即可。
}
public:
//explicit : 禁止做隐式类型转换
TestInt(int x = 0) : m_i(x) //类型转换构造函数(也是一个只带一个参数的普通构造函数),本构造函数就可以,将一个int数字转换成类类型TestInt
{
if (m_i < 0) m_i = 0;
if (m_i > 100) m_i = 100;
}
//类型转换运算符,可以把本类类型对象转换成其他类型。
operator int() const{
return m_i;
}
//operator double()const{
//
//}
int m_i;
};
class CT1{
public:
CT1(int ct){} // 类型转换构造函数
};
class CT2{
public:
CT2(int ct){} // 类型转换构造函数
};
void testfunc(const CT1& c){};
void testfunc(const CT2& c){};
class CT{
public:
void ptfunc(int tmpvalue) { cout << "ptfunc普通成员函数被调用, value=" << tmpvalue << endl; }
//类中有虚函数则编译器会给该类生成虚函数表
virtual void virtualfunc(int tmpvalue){ cout << "virtualfunc虚成员函数被调用, value=" << tmpvalue << endl; }
static void staticfunc(int tmpvalue){ cout << "staticfunc静态成员函数被调用, value=" << tmpvalue << endl; }
int m_a; //普通成员变量
static int m_stca;// 静态成员变量,属于类, 不属于对象
};
int CT::m_stca = 1; // 静态成员变量的定义
int main() {
//我们需要通过转换构造函数,和 类型转换运算符 来做到 类型转换
//一:类型转换构造函数,比如,他们能够把一个数字转换成一个类对象。
//构造函数种类:常规不带参数的(默认构造函数),带一个参数,带两个参数....
//拷贝构造函数,移动构造函数。
//特点回顾:
//a) 以类名作为函数名
//b) 没有返回值
//有一种构造函数,叫“类型转换构造函数”,主要能力是:它可以将某个其他的数据类型转换成该类类型的对象。
//类型转换构造函数的特点:
//a) 只有一个参数,该参数又不是本类的const 引用。(const &A),该参数其实就是待转换的数据类型。所以显然待转换的数据类型都不应该是本类类型。
//b) 在类型转换构造函数中,我们要指定转换的方法(在这个函数中要干什么);
TestInt ti = 12; //隐式类型转换,将数字12转换成了 TestInt对象(调用了类型转换构造函数)
//编译器用12这个数字通过调用TestInt类的类型构造函数来创建一个临时的TestInt对象,并把这个对象构造到ti这个预留空间里去了
//TestInt ti = TestInt(12); //这也是调用类型转换构造函数
TestInt ti2(22); //调用了类型转换构造函数,但这里并没有进行隐式类型转换。
//二:类型转换运算符(类型转换函数):能力和类型转换构造函数能力相反。
//是特殊的成员函数,它能够将一个类类型对象 转成 某个其他数据类型。
//格式:
//operator type() const;
//a) const 是可选项,const 表示一般不应该改变待转换对象内容,但不是必须有const
//b) type :表示要转换成的某种类型。只要是能够作为函数返回的类型,都可以;数组指针,函数指针,引用等等类型也都可以
//c) 类型转换运算符,没有形参(形参列表为空),因为类型猪娜辉运算符都是隐式执行的,所以根本也没有办法给它传递参数。
//同时,也不能指定返回类型,但是,它却能返回一个type指定的类型的值的;
//d) 必须定义为类的成员函数。
TestInt ti3 = 12;
TestInt ti4;
ti4 = 6; //编译器用6生成临时的TestInt对象(调用TestInt类型转换构造函数),又调用赋值运算符把临时对象的内容给了 ti4
//int k = ti4 + 5; // 11: 调用operator int() const 将ti4 转换成了 int ,再和5做加法运算,结果给k
//ti4 转int是隐式类型转换
int k2 = ti4.operator int() + 5;//显示调用。没有形参,所以()内为空。
//(2.1) 显示的类型转换运算符 explicit;
//(2.2) 有趣范例:类对象转换为函数指针
// operator tfpoint()
TestInt myi(12);
myi(123);//看起来是个可调用对象的感觉。相当于调用了两个函数:
//(1)类型转换运算符【转换成函数指针类型】
// (2) 通过函数指针调用具体的函数
//(myi.operator TestInt::tfpoint())(123);
//三:类型转换的二义性问题
//二义性:这么干也行,那么干也行,导致编译器不知道该怎么干,所以编译器只能报错。
TestInt aa;
//int abc = aa + 12; //二义性 如果放开的 operator double()const{}
//建议:在一个类中,尽量只出现一个类型转换运算符;
//testfunc(123); //二义性,因为123是个int类型,可以转换成CT1对象,也可以转换成CT2类型对象。
testfunc(CT1(123)); //明确调用的是 void testfunc(cosnt CT1& C) {};
//四:类成员函数指针 : 是个指针,指向类成员函数
//(4.1) 对于普通成员函数 的函数指针
//格式: 类名::*函数指针变量名 来声明普通成员函数指针,
// &类名::成员函数名 来获取类成员函数地址, “这是个真正的内存地址”;
//定义一个普通的类成员函数指针
void (CT::*myfpointpt)(int); //一个类成员函数指针变量的定义,变量名字为 myfpointpt
myfpointpt = &CT::ptfunc; // 类成员函数指针变量 myfpointpt被赋值
//大家注意:成员函数是属于类的,不属于类对象,只要有类在就有成员函数地址在。
//但是你若要使用这个成员函数指针,就必须要把它绑定到一个类对象上才能调用。
//使用函数指针的格式 : “类对象名 * 函数指针变量名”来调用,如果是个对象指针,则调用格式 “指针名->*函数指针变量名”来调用
CT ct, *pct;
pct = &ct;
(ct.*myfpointpt)(100); //对象ct ,调用指针变量 myfpointpt所指向的成员函数 : ptfunc;
(pct->*myfpointpt)(200); //对pct所指的对象,调用指针变量 myfpointpt所指向的成员函数 : ptfunc;
//(4.2) 对于虚函数
void (CT::*myfpointvirtual)(int) = &CT::virtualfunc; //“这是个真正的内存地址”;
//也必须要绑定到类对象上才能调用
(ct.*myfpointvirtual)(100); //对象 ct ,调用指针变量myfpointvirtual所指向的成员函数 virtualfunc;
(pct->*myfpointvirtual)(200);//对pct所指的对象,调用指针变量myfpointvirtual所指向的成员函数 virtualfunc;
//(4.3) 对于静态成员函数
//使用 “*函数指针变量名” 来声明静态成员函数指针,使用 “&类名::成员函数名”来获取类成员函数地址,这个也是真正的地址
//定义一个静态的类成员函数指针并赋值
void(*myfpointstatic)(int) = &CT::staticfunc;
myfpointstatic(100); //直接使用静态成员函数指针名即可调用
//五:类成员变量指针
//(5.1) 对于普通成员变量
int CT::*mp = &CT::m_a; //定义一个类成员变量指针,大家这里注意这种写法
//ox00000 ,并不是真正意义上的指针。
// 它不是指向内存中某个地址,而是该成员变量,与该类对象指针之间的偏移量。
CT ctesttmp; //当生成类对象时,如果这个类中有虚函数表,则对象中,就会有一个指向这个虚函数表的指针,这个指针占用4个字节。
ctesttmp.*mp = 189;//通过类成员变量指针来修改成员变量值,等价于ct.m_a = 189;
//(5.2) 对于静态成员变量
//这种指向静态成员变量的指针,是有真正的内存地址的;
int *stcp = &CT::m_stca; //定义一个静态成员变量指针
*stcp = 798; //等价于 CT::m_stca = 798;
cout << *stcp << endl; // 796;
system("pause");
return 0;
}