转:C++语言的15个晦涩特性
操作符重载和检查顺序
重载,(逗号),||或者&&操作符会引起混乱,因为它打破了正常的检查规则。通常情况下,逗号操作符在整个左边检查完毕才开始检查右边,|| 和 &&操作符有短路行为:仅在必要时才会去检查右边。无论如何,操作符的重载版本仅仅是函数调用且函数调用以未指定的顺序检查它们的参数。
重载这些操作符只是一种滥用C++语法的方式。作为一个实例,下面我给出一个Python形式的无括号版打印语句的C++实现
1 #include <iostream> 2 3 namespace __hidden__ { 4 struct print { 5 bool space; 6 print() : space(false) {} 7 ~print() { std::cout << std::endl; } 8 9 template <typename T> 10 print &operator , (const T &t) { 11 if (space) std::cout << ' '; 12 else space = true; 13 std::cout << t; 14 return *this; 15 } 16 }; 17 } 18 19 #define print __hidden__::print(), 20 21 int main() { 22 int a = 1, b = 2; 23 print "this is a test"; 24 print "the sum of", a, "and", b, "is", a + b; 25 return 0; 26 }
方括号的真正含义
用来访问数组元素的ptr[3]其实只是*(ptr + 3)的缩写,与用*(3 + ptr)是等价的,因此反过来与3[ptr]也是等价的,使用3[ptr]是完全有效的代码。
1 #include <stdio.h> 2 int _tmain(int argc, _TCHAR* argv[]) 3 { 4 int array[5] = {1,2,3,4,5}; 5 printf("%d\n", array[2]); 6 7 printf("%d\n", 2[array]); 8 getchar(); 9 return 0; 10 }
图灵完备的模板元编程
C++模板是为了实现编译时元编程,也就是该程序能生成其它的程序。设计模板系统的初衷是进行简单的类型替换,但是在C++标准化过程中突然发现模板实际上功能十分强大,足以执行任意计算,虽然很笨拙很低效,但通过模板特化的确可以完成一些计算:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// Recursive template for general case template < int N> struct factorial { enum { value = N * factorial<N - 1>::value }; }; // Template specialization for base case template <> struct factorial<0> { enum { value = 1 }; }; enum { result = factorial<5>::value }; // 5 * 4 * 3 * 2 * 1 == 120 |
C++模板可以被认为是一种功能型编程语言,因为它们使用递归而非迭代而且包含不可变状态。你可以使用typedef创建一个任意类型的变量,使用enum创建一个int型变量,数据结构内嵌在类型自身。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// Compile-time list of integers template < int D, typename N> struct node { enum { data = D }; typedef N next; }; struct end {}; // Compile-time sum function template < typename L> struct sum { enum { value = L::data + sum< typename L::next>::value }; }; template <> struct sum<end> { enum { value = 0 }; }; // Data structures are embedded in types typedef node<1, node<2, node<3, end> > > list123; enum { total = sum<list123>::value }; // 1 + 2 + 3 == 6 |
当然这些例子没什么用,但模板元编程的确可以做一些有用的事情,比如可以操作类型列表。但是,使用C++模板的编程语言可用性极低,因此请谨慎和少量使用。模板代码很难阅读,编译速度慢,而且因其冗长和迷惑的错误信息而难以调试。
静态实例方法
C++中可以通过实例调用静态方法也可以通过类直接调用。这可以使你不需要更新任何调用点就可以将实例方法修改为静态方法。
1
2
3
4
5
6
7
|
struct Foo { static void foo() {} }; // These are equivalent Foo::foo(); Foo().foo(); |