由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
JobHunting版 - 请教一个 c++ member function pointer 问题
相关主题
指针函数, 函数指针, 头大。。bloomberg 电面
array of pointers to functionsC++ Q79: What is the size of a pointer? and why?
怎么才能掌握好C++里面的指针和引用?面试面试官错了怎么办?
问一个c++ 函数指针的问题C++疑问:Animal a,Animal* a,哪种访问方式快
问道C的面试题void * 和 char * 有区别吗?
在子函数内开内存,返回主函数指针然后释放空间是不是很糟糕的(转载)面试问了个“master c++”的这个问题,答不出来,直接给枪毙了 (转载)
My Microsoft Phone Interview问个简单的C++ 函数参数问题
问道编程题问面试一题: OOP 设计 for "Evaluate Reverse Polish Notation"
相关话题的讨论汇总
话题: function话题: pointer话题: int话题: next话题: c++
进入JobHunting版参与讨论
1 (共1页)
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
2
不懂,帮顶
f*******t
发帖数: 7549
3
google error message
J****3
发帖数: 427
4
不传引用进update试试?
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

相关主题
在子函数内开内存,返回主函数指针然后释放空间是不是很糟糕的(转载)bloomberg 电面
My Microsoft Phone InterviewC++ Q79: What is the size of a pointer? and why?
问道编程题面试面试官错了怎么办?
进入JobHunting版参与讨论
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?

相关主题
C++疑问:Animal a,Animal* a,哪种访问方式快问个简单的C++ 函数参数问题
void * 和 char * 有区别吗?问面试一题: OOP 设计 for "Evaluate Reverse Polish Notation"
面试问了个“master c++”的这个问题,答不出来,直接给枪毙了 (转载)C++ Q90 - Q92
进入JobHunting版参与讨论
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.

相关主题
菜鸟问个C++的pointer问题array of pointers to functions
想成为嵌入式程序员应知道的0x10个基本问题 zz怎么才能掌握好C++里面的指针和引用?
指针函数, 函数指针, 头大。。问一个c++ 函数指针的问题
进入JobHunting版参与讨论
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++作为一个老的语言支持得不是很自然是
: 正常的.

相关主题
问一个c++ 函数指针的问题My Microsoft Phone Interview
问道C的面试题问道编程题
在子函数内开内存,返回主函数指针然后释放空间是不是很糟糕的(转载)bloomberg 电面
进入JobHunting版参与讨论
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); \
: } \

相关主题
C++ Q79: What is the size of a pointer? and why?void * 和 char * 有区别吗?
面试面试官错了怎么办?面试问了个“master c++”的这个问题,答不出来,直接给枪毙了 (转载)
C++疑问:Animal a,Animal* a,哪种访问方式快问个简单的C++ 函数参数问题
进入JobHunting版参与讨论
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)
: 看过多次,但不理解。

1 (共1页)
进入JobHunting版参与讨论
相关主题
问面试一题: OOP 设计 for "Evaluate Reverse Polish Notation"问道C的面试题
C++ Q90 - Q92在子函数内开内存,返回主函数指针然后释放空间是不是很糟糕的(转载)
菜鸟问个C++的pointer问题My Microsoft Phone Interview
想成为嵌入式程序员应知道的0x10个基本问题 zz问道编程题
指针函数, 函数指针, 头大。。bloomberg 电面
array of pointers to functionsC++ Q79: What is the size of a pointer? and why?
怎么才能掌握好C++里面的指针和引用?面试面试官错了怎么办?
问一个c++ 函数指针的问题C++疑问:Animal a,Animal* a,哪种访问方式快
相关话题的讨论汇总
话题: function话题: pointer话题: int话题: next话题: c++