c**z 发帖数: 669 | 1 请大家看看为什么编译通不过,谢谢. 始终说最后的函数地址不match定义 。
牛人看看。
//header file
class Function_pointer
{
public:
int next(int n);
int before( int n);
int next_after_next( int n);
typedef int (*f)(int n);
void update( int n, f pointer );
};
// .cpp file
# include
# include"Header.h"
using namespace std;
int Function_pointer::next(int n)
{
return n +1;
}
int Function_pointer::before( int n)
{
return n - 1;
}
int Function_pointer::next_after_next( int n)
{
return n + 1 + 1;
}
void Function_pointer::update( int n, f pointer )
{
pointer(n);
}
void main()
{
Function_pointer myFunc;
myFunc.update( 1, &Function_pointer::next);
} |
w****f 发帖数: 684 | |
f*******t 发帖数: 7549 | |
J****3 发帖数: 427 | |
s********i 发帖数: 145 | 5 C++ 非静态成员函数不能做callback,这是常识吧。。。确实是比较恶心的地方。 |
s********r 发帖数: 403 | 6 Function_pointer::next 不可引用,
只有把 next 定义成静态成员函数才可以这么玩。 |
r*******e 发帖数: 7583 | 7 成员函数的类型是
int (Function_pointer::*)(int n)
所以要把 typedef int (*f)(int n); 改成
typedef int (Function_pointer::*f)(int n);
另外update的函数要改成
(this->*pointer)(n);
【在 c**z 的大作中提到】 : 请大家看看为什么编译通不过,谢谢. 始终说最后的函数地址不match定义 。 : 牛人看看。 : //header file : class Function_pointer : { : public: : int next(int n); : int before( int n); : int next_after_next( int n); : typedef int (*f)(int n);
|
r*******e 发帖数: 7583 | 8 可以引用
http://stackoverflow.com/questions/990625/c-function-pointer-cl
【在 s********r 的大作中提到】 : Function_pointer::next 不可引用, : 只有把 next 定义成静态成员函数才可以这么玩。
|
b******t 发帖数: 9 | 9 从语法的角度来讲,你不可以这样引用;如果能编译过,那就是编译器的bug。
想不用static 还能callback的唯一方法,就是定义虚函数,通过虚函数指针访问目标
方法;
这其实也是个语言设计的bug。 |
s********r 发帖数: 403 | 10 这个只是是障眼法,
实际上调用的还是已经实例化对象的函数指针,
用函数指针指向某个合法地址,当然可以调用了。
在系统初始化,甚至
typedef int (*init) (int);
*((init*) 0x000f3102)(1) 都可以,只要地址合法。
对于c++,非实例化类的非静态成员函数,不可直接调用。
【在 r*******e 的大作中提到】 : 可以引用 : http://stackoverflow.com/questions/990625/c-function-pointer-cl
|
|
|
s********r 发帖数: 403 | 11 那个其实只是用了一个函数指针指向了合法地址,
还是需要实例化的对象来发动。
【在 b******t 的大作中提到】 : 从语法的角度来讲,你不可以这样引用;如果能编译过,那就是编译器的bug。 : 想不用static 还能callback的唯一方法,就是定义虚函数,通过虚函数指针访问目标 : 方法; : 这其实也是个语言设计的bug。
|
f****4 发帖数: 1359 | 12 正解
【在 r*******e 的大作中提到】 : 成员函数的类型是 : int (Function_pointer::*)(int n) : 所以要把 typedef int (*f)(int n); 改成 : typedef int (Function_pointer::*f)(int n); : 另外update的函数要改成 : (this->*pointer)(n);
|
f****4 发帖数: 1359 | 13 C++ 非静态成员函数做callback虽然麻烦一点但是是可以的
【在 s********i 的大作中提到】 : C++ 非静态成员函数不能做callback,这是常识吧。。。确实是比较恶心的地方。
|
f****4 发帖数: 1359 | 14 这里的"&"是用来给成员函数f赋值的
typedef int (Function_pointer::*f)(int n);
void update( int n, f pointer );
myFunc.update( 1, &Function_pointer::next);
在成员函数指针执行的时候必须用对象的 .* 或者是对象指针的 ->* 来调用
也就是说
Function_pointer::f fp1=&Function_pointer::next;
Function_pointer::f fp2=&Function_pointer::before;
Function_pointer::f fp3=&Function_pointer::next_after_next;
都是正确的,只要这些成员函数类型 是 int (...) (int) 即可
但是当你想调用fp1,fp2,fp3必须得
Function_pointer myFunc;
Function_pointer *myFuncpt=&myFunc;
(myFunc.*fp1)(1);
(myFuncpt->*fp2)(2);
Function_pointer myFunc1;
(myFunc1.*fp1)(1);
【在 s********r 的大作中提到】 : 这个只是是障眼法, : 实际上调用的还是已经实例化对象的函数指针, : 用函数指针指向某个合法地址,当然可以调用了。 : 在系统初始化,甚至 : typedef int (*init) (int); : *((init*) 0x000f3102)(1) 都可以,只要地址合法。 : 对于c++,非实例化类的非静态成员函数,不可直接调用。
|
f****4 发帖数: 1359 | 15 C++本身是支持非static成员函数做callback的
通过虚函数指针来做反而是不规范的。。。
【在 b******t 的大作中提到】 : 从语法的角度来讲,你不可以这样引用;如果能编译过,那就是编译器的bug。 : 想不用static 还能callback的唯一方法,就是定义虚函数,通过虚函数指针访问目标 : 方法; : 这其实也是个语言设计的bug。
|
r*******e 发帖数: 7583 | 16 同意这个
我觉得本质上是因为非static成员函数需要implicitly传入this指针
所以做callback也不是不可以,就是要多传一个对象指针
【在 f****4 的大作中提到】 : 这里的"&"是用来给成员函数f赋值的 : typedef int (Function_pointer::*f)(int n); : void update( int n, f pointer ); : myFunc.update( 1, &Function_pointer::next); : 在成员函数指针执行的时候必须用对象的 .* 或者是对象指针的 ->* 来调用 : 也就是说 : Function_pointer::f fp1=&Function_pointer::next; : Function_pointer::f fp2=&Function_pointer::before; : Function_pointer::f fp3=&Function_pointer::next_after_next; : 都是正确的,只要这些成员函数类型 是 int (...) (int) 即可
|
s********r 发帖数: 403 | 17 其实只是一个 cast, 自然必须用 function pointer 的地址,传给已实例化的
class,才能通过编译。
关于这点 compiler 是无法阻止的,也不能保证任意 cast 的正确性,需要具体 case
具体看。
就如同无法 detect 并阻止
char *ptr = NULL;
printf("%c", *ptr);
【在 f****4 的大作中提到】 : 这里的"&"是用来给成员函数f赋值的 : typedef int (Function_pointer::*f)(int n); : void update( int n, f pointer ); : myFunc.update( 1, &Function_pointer::next); : 在成员函数指针执行的时候必须用对象的 .* 或者是对象指针的 ->* 来调用 : 也就是说 : Function_pointer::f fp1=&Function_pointer::next; : Function_pointer::f fp2=&Function_pointer::before; : Function_pointer::f fp3=&Function_pointer::next_after_next; : 都是正确的,只要这些成员函数类型 是 int (...) (int) 即可
|
f****4 发帖数: 1359 | 18 不知道你想说啥。。。
C++ static 成员函数指针和非成员函数指针2者类型是不同的
class Function_pointer
{
public:
static int current(int);
int next(int n);
};
//static成员函数指针的类型是和c相同的所以不用instance就能直接调用
typedef int (*sf)(int n);
sf stcFunc= &Function_pointer::current;
cout<
//非static成员函数指针的类型则要求用instance才能调用
typedef int (Function_pointer::*f)(int n);
f fp1=&Function_pointer::next;
Function_pointer myFunc;
(myFunc.*fp1)(10);
这和cast,和引用没有任何关系
case
【在 s********r 的大作中提到】 : 其实只是一个 cast, 自然必须用 function pointer 的地址,传给已实例化的 : class,才能通过编译。 : 关于这点 compiler 是无法阻止的,也不能保证任意 cast 的正确性,需要具体 case : 具体看。 : 就如同无法 detect 并阻止 : char *ptr = NULL; : printf("%c", *ptr);
|
s********r 发帖数: 403 | 19 这些最基本的大家都知道。
那个使用非静态成员函数的本质就是 cast 了一个内存地址, not complicated,
so what?
【在 f****4 的大作中提到】 : 不知道你想说啥。。。 : C++ static 成员函数指针和非成员函数指针2者类型是不同的 : class Function_pointer : { : public: : static int current(int); : int next(int n); : }; : //static成员函数指针的类型是和c相同的所以不用instance就能直接调用 : typedef int (*sf)(int n);
|
f****4 发帖数: 1359 | 20 ===========================================================
发信人: sharkspear (鲨翁), 信区: JobHunting
标 题: Re: 请教一个 c++ member function pointer 问题
发信站: BBS 未名空间站 (Tue Jul 23 23:09:13 2013, 美东)
Function_pointer::next 不可引用,
只有把 next 定义成静态成员函数才可以这么玩。
===========================================================
你确定你知道?
"cast 了一个内存地址"
我猜一下:你管
f fp1=&Function_pointer::next;
叫做cast?
如果那样的话,g++只会警告而不禁止
sf fakeFunc=(sf)&Function_pointer::next;
fakeFunc(102); //不知道call哪去了。。。
非静态成员函数的本质就是 cast 了一个内存地址;并且调用的时候得显式提供
instance!
【在 s********r 的大作中提到】 : 这些最基本的大家都知道。 : 那个使用非静态成员函数的本质就是 cast 了一个内存地址, not complicated, : so what?
|
|
|
s********r 发帖数: 403 | 21 你直接看楼主的原贴,他是不是直接去 call 了非静态函数成员
void Function_pointer::update( int n, f pointer )
{
pointer(n);
}
所以大家都认为需要符合c++ 标准,把 next 定义成静态函数。
至于那个 trick, 就是绕过编译检查,把函数指针指向了一个 address,
并通过已经实例化的对象进行调用。
我已经说过编译器无法阻止这种 trick, 并不保证调用正确,要具体case具体看。
你刚才说的,只是把我前面讲的重复了一遍
【在 f****4 的大作中提到】 : =========================================================== : 发信人: sharkspear (鲨翁), 信区: JobHunting : 标 题: Re: 请教一个 c++ member function pointer 问题 : 发信站: BBS 未名空间站 (Tue Jul 23 23:09:13 2013, 美东) : Function_pointer::next 不可引用, : 只有把 next 定义成静态成员函数才可以这么玩。 : =========================================================== : 你确定你知道? : "cast 了一个内存地址" : 我猜一下:你管
|
t****t 发帖数: 6806 | 22 显然你对pointer to member function的认识还停留在C 语言pointer to function的
阶段. 你楼上讲的是C++定义好的语义, 没有任何问题, 保证调用正确, 有类型检查,
也没有什么trick.
【在 s********r 的大作中提到】 : 你直接看楼主的原贴,他是不是直接去 call 了非静态函数成员 : void Function_pointer::update( int n, f pointer ) : { : pointer(n); : } : 所以大家都认为需要符合c++ 标准,把 next 定义成静态函数。 : 至于那个 trick, 就是绕过编译检查,把函数指针指向了一个 address, : 并通过已经实例化的对象进行调用。 : 我已经说过编译器无法阻止这种 trick, 并不保证调用正确,要具体case具体看。 : 你刚才说的,只是把我前面讲的重复了一遍
|
f****4 发帖数: 1359 | 23 非static成员函数指针的用法不是编译器的trick,那个是C++ syntax支持的。那个用
虚函数指针的才是编译器的trick。
所以只要你正常的用非static成员函数指针,正确调用是能保证的。
-非static成员函数指针是那个类的有效非static函数指针
-调用时instance有效
我前面那个例子
fakeFunc(102);
十有八九是Segmentation fault
再有一点
sf fakeFunc=(sf)&Function_pointer::next;
//warning: converting from ‘int (Function_pointer::*)(int)’ to ‘int (*)(
int)’
Function_pointer::f fps=(Function_pointer::f)&Function_pointer::current;
//error: invalid cast from type ‘int (*)(int)’ to type ‘int (Function_
pointer::*)(int)’
编译器是禁止你把static成员函数指针cast成非static成员函数指针用的,尽管所有
instance share同一份static成员函数你还是没法像下面那样通过非static成员函数指
针来调用static成员函数
Function_pointer myFunc1,myFunc2;
Function_pointer::f fps=(Function_pointer::f)&Function_pointer::current;
(myFunc1.*fps)(10);
(myFunc2.*fps)(10);
【在 s********r 的大作中提到】 : 你直接看楼主的原贴,他是不是直接去 call 了非静态函数成员 : void Function_pointer::update( int n, f pointer ) : { : pointer(n); : } : 所以大家都认为需要符合c++ 标准,把 next 定义成静态函数。 : 至于那个 trick, 就是绕过编译检查,把函数指针指向了一个 address, : 并通过已经实例化的对象进行调用。 : 我已经说过编译器无法阻止这种 trick, 并不保证调用正确,要具体case具体看。 : 你刚才说的,只是把我前面讲的重复了一遍
|
s********r 发帖数: 403 | 24 如果希望 cast static成员函数指针, 需要修改函数指针的定义才能使用,
就变成楼主最初定义的那种函数指针模式。
一定要用指针去cast 调用非 static 成员函数,本身逻辑上有些奇怪,
因为,最终还是要有实例化的类才能发动,那不如直接用实例化类自身的成员函数,直
接调就是了,比如:
myFunc.update( 1, &Function_pointer::next);
改为
myFunc.update( 1, &myFunc.next);
又简单又明了
【在 f****4 的大作中提到】 : 非static成员函数指针的用法不是编译器的trick,那个是C++ syntax支持的。那个用 : 虚函数指针的才是编译器的trick。 : 所以只要你正常的用非static成员函数指针,正确调用是能保证的。 : -非static成员函数指针是那个类的有效非static函数指针 : -调用时instance有效 : 我前面那个例子 : fakeFunc(102); : 十有八九是Segmentation fault : 再有一点 : sf fakeFunc=(sf)&Function_pointer::next;
|
f****4 发帖数: 1359 | 25 typedef int (*sf)(int n);
sf fps = &myFunc.next;
fps(111);
error: ISO C++ forbids taking the address of a bound member function to form
a pointer to member function. Say ‘&Function_pointer::next’
error: cannot convert ‘int (Function_pointer::*)(int)’ to ‘int (*)(int)’
in initialization
typedef int (*sf)(int n);
sf fps = (sf)&myFunc.next;
fps(111);
error: ISO C++ forbids taking the address of a bound member function to form
a pointer to member function. Say ‘&Function_pointer::next’
warning: converting from ‘int (Function_pointer::*)(int)’ to ‘int (*)(int
)’
【在 s********r 的大作中提到】 : 如果希望 cast static成员函数指针, 需要修改函数指针的定义才能使用, : 就变成楼主最初定义的那种函数指针模式。 : 一定要用指针去cast 调用非 static 成员函数,本身逻辑上有些奇怪, : 因为,最终还是要有实例化的类才能发动,那不如直接用实例化类自身的成员函数,直 : 接调就是了,比如: : myFunc.update( 1, &Function_pointer::next); : 改为 : myFunc.update( 1, &myFunc.next); : 又简单又明了
|
s********r 发帖数: 403 | 26 c++ 的这种 design 并不 make sense,作为有实体的对象,更应当可以取地址。
而实际情况是非实体的类成员可以,但实例化以后被编译器禁止。
从debug 来看,其实地址是同一的。
如果按正常逻辑,要么都可以,要么都不允许,至少实体本身更具有取地址权。
(gdb) l
31 int main()
32 {
33
34 Function_pointer myFunc;
35 Function_pointer myFunc2;
36 Function_pointer* ptr = &myFunc;
37
(gdb) p myFunc2.next
$1 = {int (Function_pointer *, int)} 0x4032c4
(gdb) p Function_pointer::next
$2 = {int (Function_pointer * const, int)} 0x4032c4
int)>
(gdb) p myFunc.next
$3 = {int (Function_pointer *, int)} 0x4032c4
form
【在 f****4 的大作中提到】 : typedef int (*sf)(int n); : sf fps = &myFunc.next; : fps(111); : error: ISO C++ forbids taking the address of a bound member function to form : a pointer to member function. Say ‘&Function_pointer::next’ : error: cannot convert ‘int (Function_pointer::*)(int)’ to ‘int (*)(int)’ : in initialization : typedef int (*sf)(int n); : sf fps = (sf)&myFunc.next; : fps(111);
|
t****t 发帖数: 6806 | 27 you can use std::bind(pointer_to_member, pointer_to_object, ...) to get what
you have in mind. but that doesn't make your previous argument ("it is a
trick to cheat compiler") valid.
【在 s********r 的大作中提到】 : c++ 的这种 design 并不 make sense,作为有实体的对象,更应当可以取地址。 : 而实际情况是非实体的类成员可以,但实例化以后被编译器禁止。 : 从debug 来看,其实地址是同一的。 : 如果按正常逻辑,要么都可以,要么都不允许,至少实体本身更具有取地址权。 : (gdb) l : 31 int main() : 32 { : 33 : 34 Function_pointer myFunc; : 35 Function_pointer myFunc2;
|
f****4 发帖数: 1359 | 28 C++没有不允许你这么干,它只是强制要求你这么做的时候把this指针显示的传进去
你可以去查一下function template和bind的用法
新标准里面多了个mem_fn
【在 s********r 的大作中提到】 : c++ 的这种 design 并不 make sense,作为有实体的对象,更应当可以取地址。 : 而实际情况是非实体的类成员可以,但实例化以后被编译器禁止。 : 从debug 来看,其实地址是同一的。 : 如果按正常逻辑,要么都可以,要么都不允许,至少实体本身更具有取地址权。 : (gdb) l : 31 int main() : 32 { : 33 : 34 Function_pointer myFunc; : 35 Function_pointer myFunc2;
|
t****t 发帖数: 6806 | 29 actually, mem_fn is deprecated in c++11. bind is recommended now.
本来把代码和数据混合就是相对新的概念, C++作为一个老的语言支持得不是很自然是
正常的.
【在 f****4 的大作中提到】 : C++没有不允许你这么干,它只是强制要求你这么做的时候把this指针显示的传进去 : 你可以去查一下function template和bind的用法 : 新标准里面多了个mem_fn
|
s********r 发帖数: 403 | 30 C 很好使啊,C89/99 + ASM 是嵌入式, driver, Linux kernel开发黄金组合
【在 t****t 的大作中提到】 : 显然你对pointer to member function的认识还停留在C 语言pointer to function的 : 阶段. 你楼上讲的是C++定义好的语义, 没有任何问题, 保证调用正确, 有类型检查, : 也没有什么trick.
|
|
|
t****t 发帖数: 6806 | 31 that's a different and unrelated point.
【在 s********r 的大作中提到】 : C 很好使啊,C89/99 + ASM 是嵌入式, driver, Linux kernel开发黄金组合
|
s********r 发帖数: 403 | 32 The C++ class member function pointer is used mainly for two purposes:
[1] Implement delegate
[2] Variety show.
In the example, it looks more close to [2] as a small trick.
what
【在 t****t 的大作中提到】 : you can use std::bind(pointer_to_member, pointer_to_object, ...) to get what : you have in mind. but that doesn't make your previous argument ("it is a : trick to cheat compiler") valid.
|
s********i 发帖数: 145 | 33 我觉得没有语言层次的native支持就不应该使用,楼上楼下给出的那些解决方案,说的
好听是non-straightforward,说的不好听就是ugly...如果稍微大点的规模的程序这么
写,那么绝对是灾难性的。
【在 f****4 的大作中提到】 : C++ 非静态成员函数做callback虽然麻烦一点但是是可以的
|
t****t 发帖数: 6806 | 34 pointer to member本来就是C++的native支持, 而不是某些无知小朋友认为的trick.
【在 s********i 的大作中提到】 : 我觉得没有语言层次的native支持就不应该使用,楼上楼下给出的那些解决方案,说的 : 好听是non-straightforward,说的不好听就是ugly...如果稍微大点的规模的程序这么 : 写,那么绝对是灾难性的。
|
t****t 发帖数: 6806 | 35 这得有多无知才能说这种话.
【在 s********r 的大作中提到】 : The C++ class member function pointer is used mainly for two purposes: : [1] Implement delegate : [2] Variety show. : In the example, it looks more close to [2] as a small trick. : : what
|
f****4 发帖数: 1359 | 36 我回了这几个贴就是为了说这个用法不是某些人想当然的编译器trick;而是c++本身语
法支持的特性。
没用过这个的人看一下,心里有个数也就是了。不是什么难的东西。
规模大点的系统除非特殊原因,一般较少使用这些特性。原因很简单"Keep it Simple,
Stupid."
再抬扛就成口水仗了
【在 s********i 的大作中提到】 : 我觉得没有语言层次的native支持就不应该使用,楼上楼下给出的那些解决方案,说的 : 好听是non-straightforward,说的不好听就是ugly...如果稍微大点的规模的程序这么 : 写,那么绝对是灾难性的。
|
s********r 发帖数: 403 | 37 呵呵,得有多无聊才会用 member function pointer 调自己 class 的 member
不是杂耍表演又是什么
【在 t****t 的大作中提到】 : 这得有多无知才能说这种话.
|
s********r 发帖数: 403 | 38 我不是什么小朋友,我也从来没讲过 pointer to member function 本身是 trick,
只是上面耍的小花样用了这个 feature.
Anyway, 要是实际 project 用上面的那个 style, 保重,呵呵呵。
【在 t****t 的大作中提到】 : pointer to member本来就是C++的native支持, 而不是某些无知小朋友认为的trick.
|
f****4 发帖数: 1359 | 39 给你个小例子: Memento pattern
要是obj太大,存储obj就浪费内存了
一般类的属性函数都是成对出现 set/get XXXX
obj(status 0) <=本来是记录obj
setXXXX(value)
obj(status 1)
用成员函数的话;你只要记录一个callback就好了
obj(status 0)
callback(setXXXX,getXXXX()) <=记录callback调用时用obj.setXXXX(getXXXX());
setXXXX(value)
obj(status 1)
回退的时候在obj(status 1)上面调用记录的callback就能恢复成obj(status 0)了
可以做成宏,对现有的类不做任何修改而提供类状态回滚
【在 s********r 的大作中提到】 : 呵呵,得有多无聊才会用 member function pointer 调自己 class 的 member : 不是杂耍表演又是什么
|
r*********n 发帖数: 4553 | 40
被deprecated的是mem_fun吧,mem_fn是才加入的。
http://en.cppreference.com/w/cpp/utility/functional
【在 t****t 的大作中提到】 : actually, mem_fn is deprecated in c++11. bind is recommended now. : 本来把代码和数据混合就是相对新的概念, C++作为一个老的语言支持得不是很自然是 : 正常的.
|
|
|
s********r 发帖数: 403 | 41 可以这么用,但对于 Memento Patter,
通常是直接实现一个 undo()/redo() interface,
非要用 callback 然后外面套个宏,时间长了,维护代码的人也是愁眉苦脸。
不过这样也好,日积月累,代码就没人看懂了,老板也没办法,哈哈哈哈
【在 f****4 的大作中提到】 : 给你个小例子: Memento pattern : 要是obj太大,存储obj就浪费内存了 : 一般类的属性函数都是成对出现 set/get XXXX : obj(status 0) <=本来是记录obj : setXXXX(value) : obj(status 1) : 用成员函数的话;你只要记录一个callback就好了 : obj(status 0) : callback(setXXXX,getXXXX()) <=记录callback调用时用obj.setXXXX(getXXXX()); : setXXXX(value)
|
f****4 发帖数: 1359 | 42 我当然知道通常是怎么做的了。都已经说了obj size太大,需要大量记录对象状态的时
候严重浪费空间,生成销毁instance的时候很慢。
宏是你推崇的Linux kernel开发黄金组合之一C程序员最喜欢的东西,我是很反感这个
特性的。C++里面inline就好了。当然了,这是题外话。
再给你扯个题外话,你做实际的产品的时候,一个功能修改的代码越少,出错的可能越
小;需要测试维护的时间就越小。
你要是做过实际 C 产品而不是个半吊子,就应该看过到类似用函数指针实现dynamic
dispatch的东西;C++里面也可以用成员函数指针array实现类似的东西。
【在 s********r 的大作中提到】 : 可以这么用,但对于 Memento Patter, : 通常是直接实现一个 undo()/redo() interface, : 非要用 callback 然后外面套个宏,时间长了,维护代码的人也是愁眉苦脸。 : 不过这样也好,日积月累,代码就没人看懂了,老板也没办法,哈哈哈哈
|
s********r 发帖数: 403 | 43 宏,不是乱用地,
大规模开发 discourage 宏函数的使用,核心宏函数引入必须通过核心开发人员。
通常c初学者会花里胡哨的模范一些宏的高级特性,不过大家成长过程中都会有这个过
程,anyway,这个扯太远了。
【在 f****4 的大作中提到】 : 我当然知道通常是怎么做的了。都已经说了obj size太大,需要大量记录对象状态的时 : 候严重浪费空间,生成销毁instance的时候很慢。 : 宏是你推崇的Linux kernel开发黄金组合之一C程序员最喜欢的东西,我是很反感这个 : 特性的。C++里面inline就好了。当然了,这是题外话。 : 再给你扯个题外话,你做实际的产品的时候,一个功能修改的代码越少,出错的可能越 : 小;需要测试维护的时间就越小。 : 你要是做过实际 C 产品而不是个半吊子,就应该看过到类似用函数指针实现dynamic : dispatch的东西;C++里面也可以用成员函数指针array实现类似的东西。
|
f****4 发帖数: 1359 | 44 既然扯到宏,就再说两句。
我讨厌宏就是因为每次看到宏,都得给它脑补(在大脑里给它补全)。我觉得这个在阅
读习惯上是非常反人性的。。。。我知道现在的一些ide能够自动补全,但是还是习惯
了用vim。vim下面有啥好的宏展开插件?
还有就是gdb的时候,就是非优化,带编译信息,要是宏里面出错,也就是定位在调用
宏的地方。gdb能支持更准确的地位不?
【在 s********r 的大作中提到】 : 宏,不是乱用地, : 大规模开发 discourage 宏函数的使用,核心宏函数引入必须通过核心开发人员。 : 通常c初学者会花里胡哨的模范一些宏的高级特性,不过大家成长过程中都会有这个过 : 程,anyway,这个扯太远了。
|
t****t 发帖数: 6806 | 45 哦, 那是我记错了. 反正一般STL用bind就可以了, 几乎所有的情况都包括了.
【在 r*********n 的大作中提到】 : : 被deprecated的是mem_fun吧,mem_fn是才加入的。 : http://en.cppreference.com/w/cpp/utility/functional
|
t****t 发帖数: 6806 | 46 gcc编译的时候用-g3可以包含macro, 新的gdb可以用, 不记得哪个版本开始的了.
【在 f****4 的大作中提到】 : 既然扯到宏,就再说两句。 : 我讨厌宏就是因为每次看到宏,都得给它脑补(在大脑里给它补全)。我觉得这个在阅 : 读习惯上是非常反人性的。。。。我知道现在的一些ide能够自动补全,但是还是习惯 : 了用vim。vim下面有啥好的宏展开插件? : 还有就是gdb的时候,就是非优化,带编译信息,要是宏里面出错,也就是定位在调用 : 宏的地方。gdb能支持更准确的地位不?
|
t****t 发帖数: 6806 | 47 这很正常啊, 比如你要实现一堆interchangable的algorithm, 而且你需要动态切换这
时候用virtual function或许不是很方便.
【在 s********r 的大作中提到】 : 呵呵,得有多无聊才会用 member function pointer 调自己 class 的 member : 不是杂耍表演又是什么
|
f****4 发帖数: 1359 | 48 oh 多谢,我去查一下 g3
【在 t****t 的大作中提到】 : gcc编译的时候用-g3可以包含macro, 新的gdb可以用, 不记得哪个版本开始的了.
|
s********r 发帖数: 403 | 49 不知道下面这种满不满足你的需求
一般来讲,宏函数短小,主要还是靠精确的设计不靠debug
$ cat macro.c
#include
#define PRINT(str) \
do \
{ \
int i = 1; \
printf("%s %dn", (str), i); \
} \
while (0);
int main(void)
{
const char *sz_in = "Hello";
PRINT(sz_in);
return 0;
}
gcc -ggdb3 macro.c
(gdb) info MACRO PRINT
Defined at /usr/local/src_test/macro.c:3
#define PRINT(str) do { int i = 1; printf("%s %dn", (str), i); } while (0);
(gdb) si
0x0000000000400540 15 PRINT(sz_in);
(gdb) p i
$1 = 1
(gdb) p sz_in
$2 = 0x40064c "Hello"
【在 f****4 的大作中提到】 : 既然扯到宏,就再说两句。 : 我讨厌宏就是因为每次看到宏,都得给它脑补(在大脑里给它补全)。我觉得这个在阅 : 读习惯上是非常反人性的。。。。我知道现在的一些ide能够自动补全,但是还是习惯 : 了用vim。vim下面有啥好的宏展开插件? : 还有就是gdb的时候,就是非优化,带编译信息,要是宏里面出错,也就是定位在调用 : 宏的地方。gdb能支持更准确的地位不?
|
f****4 发帖数: 1359 | 50 -ggdb3 之前没用过
【在 s********r 的大作中提到】 : 不知道下面这种满不满足你的需求 : 一般来讲,宏函数短小,主要还是靠精确的设计不靠debug : $ cat macro.c : #include : #define PRINT(str) \ : do \ : { \ : int i = 1; \ : printf("%s %dn", (str), i); \ : } \
|
|
|
h**6 发帖数: 4160 | 51 为什么宏定义都喜欢用
do{}
while(0)
看过多次,但不理解。 |
r*******e 发帖数: 7583 | 52 这样宏调用后面可以加分号,语法看起来和函数调用一样
【在 h**6 的大作中提到】 : 为什么宏定义都喜欢用 : do{} : while(0) : 看过多次,但不理解。
|
s********r 发帖数: 403 | 53 还可以用来加局部变量
不过这些都不是有意思的地方, 找个学过c 的新手,
用 coding standard 好好 training 一个月,就都学会了。
c的好处还是用来设计实时系统,或驱动设备, 什么 I2C, DMA, SCSI,
很多硬件相关协议比我们出生得更早,
而且不能说有权威人士想出了个新的idea, 一拍脑袋,“前面的全不算,把interface
都改掉”,那硬件厂商马上就跳起来了。
这些相对稳定的东西,才是c 程序员饭碗的来源
【在 h**6 的大作中提到】 : 为什么宏定义都喜欢用 : do{} : while(0) : 看过多次,但不理解。
|