在"深入函数指针"中最后提供的一个例子并不是一种好的方式:
1:需要显式的初始化函数指针。
2:没有编译期的静态检查,因为不同类之间的任何成员函数都是可以相互转换的,这是不安全的。
这里提供另外一种方式,该方式能够解决上面的两个问题.
假设需要提供的静态接口为:
void func0(int);
int func1();
那么将接口用template实现:
//! The static interface class
template
class StaticInterface
{
public:
typedef T Impl;
public:
//! interface function 0
void func0(int arg)
{
((Impl*)this)->func0_impl(arg);
}
//! interface function 1
int func1()
{
return ((Impl*)this)->func1_impl();
}
};
//! Impl class 0
class ImplClass0 : public StaticInterface
{
public:
//! interface function 0
void func0_impl(int arg)
{
// Do something
}
//! interface function 1
int func1_impl()
{
// Do something
}
};
//! Impl class 1
class ImplClass1 : public StaticInterface
{
public:
//! interface function 0
void func0_impl(int arg)
{
// Do something
}
//! interface function 1
int func1_impl()
{
// Do something
}
};
说明:
1:因为在template中,显式的类型转化完成了在对函数指针初始化的工作,所以解决了第一个问题。
2:如果在实现类中,没有提供对应的实现,那么在编译期template实例化的时候将会产生未定义错误。并且对于函数的参数类型和范围类型具有静态类型检查(在实例化的时候检查),这比原来的实现更安全。
3:这里在具体的实现类中,没有多态的使用,不会引入多态的消耗。
不足:
1:这里实现类中的函数名没有采用和接口中的函数名一样,是为了避免如果实现类中没有实现对应的接口或者函数签名不对,将会引起无穷递归的调用。因此这成了一种额外的接口类对实现类的强制要求。
2:在同一工程中并不能对不同的实现同时使用一个接口名(使用typedef定义对外提供的接口名,而多态可以满足上面的要求),所以这只能是在不同平台下的一种定义接口的方式;当在不同平台的时候,通过修改typedef StaticInterface Interface中的ImplType来实现跨平台,而不影响程序代码中对Interface的引用。并且具体的实现类也应该以typedef的名字提供给使用者,避免使用者对实现的依赖。不同平台之间只能依赖于Interface提供的信息。
阅读(827) | 评论(0) | 转发(0) |