今天听到一个朋友来TX面试,又问到了生僻的C++关键字,那个汗,记得我那个时候面试的时候也被问到过,特总结如下:
bad_typeid
很生僻,基本在几年的开发中没有用过,要理解bad_typeid这个关键字,首先得看下typeid这个关键字的使用,下面是一段英文描述:
The typeid operator will accept a pointer when dereferenced evaluates to a type:typeid(*P);
If the pointer points to a null value then the typeid operator will throw a bad_typeid exception.
也就是说,当typeid这个操作符应用到一个空指针上的时候,会抛出一个bad_typeid异常,bad_typeid本质是一个类,定义在typeinfo文件中。见下面的例子,来之msdn,注意至少使用vs2003进行测试,vc6没有实现:
- // expre_bad_typeid.cpp
- // compile with: /EHsc /GR
- #include <typeinfo.h>
- #include <iostream>
- class A{
- public :
- // object for class needs vtable
- // for RTTI
- virtual ~A();
- };
- using namespace std;
- int main() {
- A* a = NULL;
- try {
- cout << typeid(*a).name() << endl; // Error condition
- }
- catch (bad_typeid){
- cout << "Object is NULL" << endl;
- }
- }
bad_cast
这个关键字和bad_typeid类似,是dynamic_cast转换失败时(一般是错误的想把基类转换为子类时,此时转换结果为空指针),会抛出的异常。
Type of the exceptions thrown by dynamic_cast when they fail the run-time check performed on references to polymorphic class types.
The run-time check fails if the object would be an incomplete object of the destination type.
Its member what returns a null-terminated character sequence identifying the exception.
Some functions in the standard library may also throw this exception to signal a type-casting error.
bad_cast也是一个类,定义在typeinfo文件中。看下面的例子,请至少使用vs2003(vc6对dynamic_cast实现都有问题)编译:
- // bad_cast example
- #include <iostream>
- #include <typeinfo>
- using namespace std;
- class Base { virtual void Member(){}};
- class Derived : Base {};
- int main () {
- try
- {
- Base b;
- Derived& rd = dynamic_cast<Derived&>(b);
- }
- catch (bad_cast& bc)
- {
- cerr << "bad_cast caught: " << bc.what() << endl;
- }
- return 0;
- }
mutable
类的const成员函数是不能修改类的成员变量的(非静态数据成员),这个是编译器就保证的,但是如果想呢?那就用mutable吧,给成员变量用这个关 键字修饰后,编译器就不会找你的麻烦了,其实这个关键字也是被诟病比较多的,到底有什么用或者什么时候该用还没有什么结论,因为这个关键字有破坏类的封装 性的嫌疑。看个小例子:
- class TestMutable
- {
- public :
- TestMutable()
- {
- m_data = 0;
- }
- int changeValue() const
- {
- return ++m_data;
- }
- private :
- // int m_data; // 编译会有错误:error C2166: l-value specifies const object
- mutable int m_data; // 这个没有问题
- };
- int main( int argc, char * argv[])
- {
- TestMutable tsMutable;
- cout << tsMutable.changeValue() << endl;
- cout << tsMutable.changeValue() << endl;
- return 0;
- }
volatile
这个关键字以前介绍过,就不述说了。见http://blog.csdn.net/magictong/archive/2008/10/29/3175793.aspx 。
explicit
这个关键字有时候还是有用的,作用是禁止单参数的构造函数被自动类型转换(往往是将一个基本类型转换成一个对象,而且很隐晦)。用来修饰类的构造函数,表 明该构造函数是一个显示的构造函数,而不是隐式的构造函数,编译器针对隐式构造函数在遇到赋值运算符时会执行很多额外的自动转换,而用这个关键字就是告诉 编译器,别忙活啦,不要多此一举,这不是我想要的。
- class ArrExplicit
- {
- public :
- // ArrExplicit(int size) // 使用这句,编译器并不报错
- explicit ArrExplicit( int size) // 下面arrExp = 102;编译器会报错
- {
- m_size = size;
- }
- private :
- int m_size;
- };
- int main( int argc, char * argv[])
- {
- ArrExplicit arrExp(100);
- arrExp = 102; // 用explicit修饰后,编译报错
- return 0;
- }