介绍一个雕虫小技:编译期判断类的继承性。具体来说就是类型U是否继承自类型T。该技术的灵感和源头来自Andrei Alexandrescue的《Modern C++ Design》。原书中描述的此技术有一个小小的bug。
源代码
template <class T , class U>
class __conversion
{
static char test(U);
static double test(...);
static T maket();
public:
enum{exists = sizeof(test(maket())) == sizeof(char) };
enum{exists2way = exists && __conversion<U,T>::exists};
enum{sametype = false};
};
template <class T>
class __conversion<T,T>
{
public:
enum{exists = 1};
enum{exists2way = 1};
enum{sametype = 1};
};
//判断T是否是U的父类或者T和U是相同类型
#define SUPERSUBCLASS(T,U) (kimi_boost::__conversion<const U*,const T*>::exists &&\
!kimi_boost::__conversion<const T*,void*>::sametype)
//判断T是否是U的父类
#define SUPERSUBCLASS_STRICT(T,U) (SUPERSUBCLASS(T,U) &&\
!kimi_boost::__conversion<const T, const U>::sametype)
测试程序
class a{};
class b : public a{};
void supersub_test()
{
using std::cout;
using std::endl;
cout<<SUPERSUBCLASS(int,unsigned)<<endl;
cout<<SUPERSUBCLASS(int,int)<<endl;
cout<<SUPERSUBCLASS_STRICT(int,int)<<endl;
cout<<SUPERSUBCLASS(std::forward_iterator_tag,std::random_access_iterator_tag)<<endl<<endl;
cout<<SUPERSUBCLASS(a,a)<<endl;
cout<<SUPERSUBCLASS(a,b)<<endl;
cout<<SUPERSUBCLASS(b,b)<<endl;
cout<<SUPERSUBCLASS(b,a)<<endl<<endl;
cout<<SUPERSUBCLASS_STRICT(a,a)<<endl;
cout<<SUPERSUBCLASS_STRICT(a,b)<<endl;
cout<<SUPERSUBCLASS_STRICT(b,b)<<endl;
cout<<SUPERSUBCLASS_STRICT(b,a)<<endl;
}
程序结果
0
1
0
1
1
1
1
0
0
1
0
0
分享到:
相关推荐
在编译期,虚函数并不会被静态编译,而是在运行期根据对象实例来动态判断要调用的函数。 在调用虚函数时,系统会首先检查对象的申明类,看是否有该虚函数的声明,如果有,那么它就不会立刻执行该函数,而是转去检查...
4. **符号表的信息栏中登记了每个名字的有关属性,如类型、作用域、地址和生存期等。** 5. **一个确定有穷自动机由五部分组成:状态集、输入字母表、转移函数、初态和终态集。** 6. **最常用的两类语法分析方法是...
- **运行时固定性**:继承关系在编译期确定,无法在运行时动态改变。 #### Coad规则 使用继承时应遵循一套规则,确保继承关系的合理性: - 子类应表示“是一个…的特殊类型”,而非“扮演一个角色”。 - 子类不应...
- **类型安全**:确保程序在编译期就能检测到类型错误,提高代码的安全性。 - **编译器作用**:编译器在编译过程中对类型进行验证,确保变量和表达式的类型正确无误。 - **泛型擦除**:尽管Java支持泛型,但实际执行...
一般异常是编译期需要处理的异常,必须在方法签名中声明或捕获。 6. Servlet生命周期: Servlet的生命周期包括初始化(init)、服务(service)、销毁(destroy)三个阶段。Servlet通常由服务器创建单个实例,处理...
`在字符串常量池中只会创建四个`String`对象,因为字符串字面量在编译期就会优化合并。 ### 38. `try`与`finally`执行顺序 在`try`块中有`return`语句时,`finally`块中的代码会在`return`之前执行,确保资源的...
`只创建了一个`String`对象,因为在编译期,常量字符串的连接会被优化为一个字符串。 #### 38. try-finally语句的执行顺序 在`try`块中的`return`语句执行之前,`finally`块一定会被执行。如果`finally`块中有`...
在编译期会被优化为常量字符串,因此不会创建新的`String`对象。 **1.38 try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?** `finally`块中的...
需要注意的是,尽管这些类型都可以用于`case`标签,但它们必须是在编译期可知的常量表达式,例如字面量或`final`常量。 #### 七、特殊关键字与语句 **问题7:** Math,String是不可继承的。(final类) **答案解析:...
- **编译期异常**:这类异常是可以通过编译器检查出来的,如`NullPointerException`、`ArrayIndexOutOfBoundsException`等。 - **运行期异常**:这类异常在程序运行时才可能发生,如`IOException`、`SQLException`...
变量必须在其使用前进行声明,这是编译期检查的一部分,以确保变量在使用时已正确初始化。 ### 二十二、多维数组的特点 多维数组可以是稀疏的,意味着数组的部分元素可以为空。理解和利用这一特性对于优化内存使用...
5. 模板元编程(template metaprogramming),利用模板在编译期进行计算和逻辑判断。 6. STL中的容器(如vector, list, set等)、迭代器(iterator)和算法,提升代码的可读性和效率。 7. 文件I/O操作,包括文本文件...
14. **注解**:注解提供了一种元数据方式,可以用于编译期或运行期处理。通过实例,你可以了解自定义注解的创建和使用。 15. **Swing和JavaFX**:Java提供了GUI编程库,如Swing和JavaFX,用于创建桌面应用。实例...
`在编译期会被优化为`String s = "abcd";`,因此只创建了一个对象。但如果使用变量拼接,如`String s = a + b + c + d;`,则会根据实际情况创建多个对象。 #### 38\. try-catch-finally的执行顺序 在`try`块中有`...
`只创建了一个`String`对象,因为字符串常量在编译期就会合并。 #### 38. `try...finally`语句中的`finally`执行顺序 - `finally`块总是会被执行,无论`try`块中是否有`return`。 - 如果`try`块中有`return`语句,...
### 黑马程序员入学Java知识 #### Java概述与基础知识 1. **何为编程?... - 继承Thread类:直接使用Thread类的start()方法启动线程。 - 实现Runnable接口:需要通过Thread类启动。 4. **线程的生命周期** ...
2. 实现编译期类型计算,增强了代码的通用性和易用性。 3. 可以优化代码结构,减少运行时的开销。 然而,模板元编程也存在一些挑战和缺点: 1. 代码可读性和可维护性降低,由于编译期的复杂计算,模板代码往往难以...