呵呵,废话不多说,先看看到底是啥好玩的语言特性~~
1.
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
int main(int argc,char* argv[])
{
char a[20]=“world”;
printf(“%c\n”,a[2]);
printf(“%c\n”,2[a]);
return 0;
}
对于这段代码,你觉得是否会编译通过,并且正确运行呢?
2.
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
class Foo {
public:
static void bar() {
std::cout << “I am bar()” << std::endl;
}
};
int main(int argc,char* argv[])
{
Foo * foo = NULL;
foo->bar();
return 0;
}
这段代码,你觉得输出的结果是啥呢?还是core掉?
===================我是华丽的分割线===================
在公司论坛上偶尔发现了这样几个好玩的东西,很遗憾的告诉大家,上面两个程序都可以编译通过并正确运行(windows下gcc 3.4.5)
先给大家贴一下运行结果吧
1.
其实对于第一个小程序,可以简单的这样想:
a[2] == *(a+2) == *(2+a) == 2[a]
但是对于第二个程序的话,就实在想不通啦,需要去看一下C++内部的实现才行啦~
bobby on #
第二应该是 static member function 没有this指针。其地址类型是一个“nomember的函数指针”。 上面的调用内部转换为 : bar( (Foo*)0 ); 在C++对象模型里面有讲。
Reply
Dante on #
多谢bobby指点~~~~ 发现我的每篇博客的疑问总有牛人能帮助解答,真希望这个博客能成为大家共同交流的地方~~呵呵~
Reply
依云 on #
这个已经看过啦,原文好像是在 stackoverflow ,也有一些其他的博客转了部分。
Reply
Dante on #
是吗?我是在公司内部论坛看到的,觉得好玩就测试了一下~~~大家看着玩玩就行,本来就没啥实用价值……
Reply
王李李 on #
其实bobby 说法欠妥,可以试试把那个static去掉,程序照样能运行。
实质上:
对于面向对象的语言来说 所谓的面向对象仅仅是语言层的封装,或者说是编译器的封装而已
C++代码最终会编译成机器语言,而机器语言是"面向过程"的,不存在所谓的面向对象
可以用面向过程的C语言代码来理解C++编译器
上面那个C++函数声明会转为
_Foo_bar_v_(Foo *this)
{
std::cout << "I am bar()" <bar(); 调用直接会被C++编译器转为 _Foo_bar_v_(Foo *foo); 这条语句
注意上句的foo其实就是this指针了
上面那个函数运行成功 主要在于你那个bar函数里面没有调用任何的成员变量 你可以试试往Foo添加一个成员变量(不是成员函数) 程序会core掉
另外调用虚函数也会core 这和虚函数实现密切相关
对象模型是C++学习里面比较偏门的hacker技术 我觉得即使理解了也对于用C++设计软件并没有太大的帮助(建议看看刘未鹏的博客 学习C++ 实践者的方法)
对于C++设计架构大规模软件 我也是个菜鸟 也不太好多说了
Reply
Dante on #
哈哈,高手一个个冒出来啦~~
我刚试了一下在bar函数里添加成员变量的调用,代码如下:
class Foo {
public:
static int a;
public:
static void bar() {
a=10;
std::cout << "I am bar()" << std::endl;
}
};
代码是无法编译通过的:
test2.cpp:(.text$_ZN3Foo3barEv[Foo::bar()]+0x8): undefined reference to `Foo::a'
但是去掉foo->bar();这行调用,就会编译正常。
Reply
王李李 on #
test2.cpp:(.text$_ZN3Foo3barEv[Foo::bar()]+0x8): undefined reference to `Foo::a'
主要是a是静态成员
而静态成员需要在类外单独定义的
static int Foo::a;
博主忘了加这句话..
另外 我的意思是a不是静态成员的情况下会core
Reply
王李李 on #
另外说句 我用了两年多了vim 来看了博主的vim用法 才知道自己用vim有多菜 hoho~~ 所以订了你的博客 主要想向你学用vim
Reply
Dante on #
哈哈,我这边会尽量多的和大家分享VIM的使用啊~
Reply
王李李 on #
格式有误,补发:
可以用面向过程的C语言代码来理解C++编译器
上面那个C++函数声明会转为
_Foo_bar_v_(Foo *this)
{
std::cout << "I am bar()" <bar(); 调用直接会被C++编译器用 _Foo_bar_v_(Foo *foo); 代替
注意上句的*foo其实就是this指针了
Reply
小保哥 on #
static成员函数是没有this指针的
Reply
GuoJing on #
有点意思,呵呵,虽然不经常弄C++
Reply
GuoJing on #
不过要说的是,在项目开发中,这样写是非常危险的,其实最主要的是要整个team按照一个标准去写,否则可读性,可维护性马上降到最低。
虽然我很少写c++,一般就是写算法用到,但是从任何语言上来说,一些特别奇怪的特性还是少用为好,要是我是老板的话我非得气死不可。。呵呵
Reply
Dante on #
哈哈,本来就是纯属消遣啦~~ 如果真在项目里写出这样的代码,那就完全是找抽啦~~
Reply
huubby on #
第一个问题有点意思,第二个问题楼上各位已经讲的很清楚了
Reply
egmkang on #
第一个问题其实有一点好玩的地方,就是C里面没数组.
int a[10];
我们通过下标访问a[1]元素,其本质就是*(a+1).
所以1[a]也就是*(1+a),有区别么??
没有.
第二个没有Down掉,我认为是没有访问过this指针,否则就Down掉了.
OO的最大特性是虚函数指针/虚函数表,其他的部分都可以成为OB(我自己这么叫~~).OB的部分在任何语言里面都能实现,无非就是this指针+函数.this指向的是数据,函数就是方法~~编译器在编译C++程序的时候,偷偷摸摸添加上去了this指针,我认为.....虽然我一直不知道他的参数怎么传递的
Reply
egmkang on #
int * const a=NULL;
a++;
int b[10];
b++;
在VC下面看到的错误一样滴~~
Reply
Dante on #
呃,这个是因为这个指针是不可以改变值的吧
Reply
egmkang on #
恩,我认为那俩是一样的..
b也是一个const 指针.....
呵呵
Reply