Redian新闻
>
请教一个C++中function pointer的问题。
avatar
请教一个C++中function pointer的问题。# Programming - 葵花宝典
q*7
1
2009年05月27日 20:40:45  来源:新华网
温家宝主持召开国务院常务会议研究部署进一步稳定外需的政策措施
新华网北京5月27日电 国务院总理温家宝27日主持召开国务院常务会议,研
究部署进一步稳定外需的政策措施。
会议指出,扩大内需是我国应对国际金融危机、促进经济长远发展的长期战略方针
,而稳定外需对于增加就业、促进企业发展、进而拉动国内消费具有重要作用,也为调
整经济结构、转变经济发展方式创造有利条件。今年以来,中央及时出台了一系列支持
对外贸易发展的政策措施,对减缓国际金融危机冲击、提振出口企业信心、保持我国出
口竞争力产生了积极效果。当前和今后一段时期,外部需求萎缩导致出口减少仍然是我
国经济增长面临的最大困难。必须坚持扩大内需和稳定外需相结合,通过扎实细致的工
作,千方百计稳定外需,努力把国际金融危机对我国外贸的影响降到最低程度。
avatar
p*e
2
推rotel功放,顺便推HD650
这样的产品是不是新的比老的多?尤其是国内的?
预算300 性价比第一
胆机石机都可以
偏向于胆机
avatar
w*e
3
本公司为塑料制造厂,现因扩建,急招如下职位。
希望大家都多内推同胞,找工作多团结。
1. entry level process engineer
MS in chemical eng. Basic knowledge/experience in polymer testing,
modification,properties,etc. need to work in production line. team player,
hard working, self motivated .
2. entry level electrical engineer
MS in electrical eng. or related major. Knowledge base of products,
technologies, processes, services and systems. knowledge of designing,
developing and introducing electrical and electronics components and systems
in medium/ high voltage facility. Experience of control systems, logic
modeling and prototyping, software integration is plus.Hands-on practical
technical experience and a good appreciation of production line is desired.
3. Marketing & Sales Associate
MS in Marketing or MBA. Serve customer base by processing both retail and
wholesale orders.Outbound phone sales and support to prospective and
existing customers.Assist in developing and maintaining effective business
relationships with customers, professionals and external business contacts.
Travel to shows and conventions to meet with customer base and present
products.analyze and track marketing efforts.
Recent graduates are encouraged to apply. successful Candidates need legal
working permit in United, like OPT or CPT. Company is supporting H1B.
candidate need to enable to work before Jul.
Plant located in louisia na. salary vary from 40k to 60k.
If you are interested in above positions, you can 'duan' me in MITbbs
or send resume to email [email protected]
/* */
good luck
avatar
S*s
4
讲的是冷战那会苏联间谍潜伏在美国的故事,精彩。
avatar
G*U
5
【 以下文字转载自 GunsAndGears 讨论区 】
发信人: GoodToCU (无心), 信区: GunsAndGears
标 题: 警察很感谢主动告诉他你有枪。
发信站: BBS 未名空间站 (Fri Apr 12 14:50:00 2013, 美东)
(严重声明:
携枪有危险
要遵守交规,跟有无携枪无关。)
在路上被抓了。没停STOP加超速。
当时就感觉一定要给市政府增收了。
警察来了之后要驾照和保险的时候,
把枪证和驾照都给了他,告诉他我
有一只loaded pistol(不说gun)
在手套箱,我要拿保险就要打开手套箱。
警察当时就非常感激的样子。先专门
感谢我提前告诉他有枪。但又说没关系,
只要你不去拿枪,尽管去拿保险和注册。
我当时心里嘀咕了一句算你狠,当然
脸上还是一本正经的样子。
给他看过后,他拿着驾照和枪证回到自己
的车边,在对讲机里讲了几句。又在
自己的电脑上敲了几下。两三分钟后
回来告诉我说今天不给你写ticket了,
就给你一个口头警告吧。他又唐一遍STOP
要停,限速是30不要超速。
临走的时候又专门感谢了一遍我提前告诉
他车里有枪。
avatar
T*s
6
【 以下文字转载自 Military 讨论区 】
发信人: TomsnReuters (汤生撸透射), 信区: Military
标 题: 黄秋园老师有这等交际实力,混苦逼的学术圈太可惜了
发信站: BBS 未名空间站 (Sat Jul 27 11:35:51 2019, 美东)
要换娱乐圈早辗压范冰冰成首富了
avatar
g*l
7
一个模块,原先是在C中写的,现在要用C++重新写,因为要添加新的功能。
情况是如下:
程序运行中,能够拿到一段数据,存在连续的memory中,uint8_t *data={30,23,.....
...},data[1]用来当tag_id用,不同tag_id要调用不同对象的处理函数,data[2]是表
示数据的长度。
在原来的C中,我是建立了一个 function pointer look up table,用data[1]来搜索,
返回相应的function pointer : void(*pfunc)(uint8_t* in_data_p,uint8_t * out_
result_p).
在C++中,现在每个对象都是一个单独的class,从base class继承来的。
class base_class
{
public:
uint8_t tag_id;
std::vector result;
public:
virtual ProcessData(uint8_t * in_data_p);
};
然后每个对象的class定义如下:
class obj_10: public base_class //10 is the tag_id
{
private:
// other members
public:
virtual ProcessData(uint8_t * in_data_p); //to override the one in base_
clss.
};
我定义了一个template
template
void obj_process_data(uint8_t *in_data_p,T& obj)
{
obj.ProcessData(in_data_p);
}
这样当我在程序中拿到 in_data_p的时间,进而拿到tag_id,调用 obj_process_data<
obj_10>(in_data_p)就可以了。
我现在是用switch(tag_ID){ case: 10... case 20...}这样来决定T的类型的,一共
100多个case,以后还要增加新的case,维护起来很麻烦啊。
请问有没有别的办法如同C中通过一个函数来查询一下,就可以决定T的类型?
谢谢。
avatar
p*e
8
继续求

推rotel功放,顺便推HD650
这样的产品是不是新的比老的多?尤其是国内的?
预算300 性价比第一
胆机石机都可以
偏向于胆机

【在 p********e 的大作中提到】
: 推rotel功放,顺便推HD650
: 这样的产品是不是新的比老的多?尤其是国内的?
: 预算300 性价比第一
: 胆机石机都可以
: 偏向于胆机

avatar
s*t
9
最新这一季故事发展太慢,明显进入鸡肋节奏

【在 S****s 的大作中提到】
: 讲的是冷战那会苏联间谍潜伏在美国的故事,精彩。
avatar
p*g
10
看来备把枪还是很重要的
avatar
EM
11
是不是可以用factory的design来写个meta program解决这个问题?

..

【在 g***l 的大作中提到】
: 一个模块,原先是在C中写的,现在要用C++重新写,因为要添加新的功能。
: 情况是如下:
: 程序运行中,能够拿到一段数据,存在连续的memory中,uint8_t *data={30,23,.....
: ...},data[1]用来当tag_id用,不同tag_id要调用不同对象的处理函数,data[2]是表
: 示数据的长度。
: 在原来的C中,我是建立了一个 function pointer look up table,用data[1]来搜索,
: 返回相应的function pointer : void(*pfunc)(uint8_t* in_data_p,uint8_t * out_
: result_p).
: 在C++中,现在每个对象都是一个单独的class,从base class继承来的。
: class base_class

avatar
d*0
12
你对黑嗓哪里又不满意了啊。。
avatar
h*o
13
第三季哪里有看?

【在 s****t 的大作中提到】
: 最新这一季故事发展太慢,明显进入鸡肋节奏
avatar
X*r
14
首先你是不是什么地方弄错了,运行时才确定的类型使用模板并无帮助。
其次这种情况一般来说是搞一个注册表把tag_id和相应的类对应起来,
实现上可以用一个宏减少复制类似的代码。

..

【在 g***l 的大作中提到】
: 一个模块,原先是在C中写的,现在要用C++重新写,因为要添加新的功能。
: 情况是如下:
: 程序运行中,能够拿到一段数据,存在连续的memory中,uint8_t *data={30,23,.....
: ...},data[1]用来当tag_id用,不同tag_id要调用不同对象的处理函数,data[2]是表
: 示数据的长度。
: 在原来的C中,我是建立了一个 function pointer look up table,用data[1]来搜索,
: 返回相应的function pointer : void(*pfunc)(uint8_t* in_data_p,uint8_t * out_
: result_p).
: 在C++中,现在每个对象都是一个单独的class,从base class继承来的。
: class base_class

avatar
s*t
15
ttmeiju

【在 h**********o 的大作中提到】
: 第三季哪里有看?
avatar
g*l
16
对,就是想搞一个LUT把tag_id和相应的类对应起来,可以不知道怎么样搞啊。
就是tag_id是动态生成的,宏也没法用啊。
有没有什么例子可以参考?
非常感谢

【在 X****r 的大作中提到】
: 首先你是不是什么地方弄错了,运行时才确定的类型使用模板并无帮助。
: 其次这种情况一般来说是搞一个注册表把tag_id和相应的类对应起来,
: 实现上可以用一个宏减少复制类似的代码。
:
: ..

avatar
n*t
17
good site, thanks

【在 s****t 的大作中提到】
: ttmeiju
avatar
t*t
18
如果我没看错的话, 你的问题不在于决定T的类型, 而是如何从tag_id产生一个T的对象
. 有了T的对象, 你就可以用virtual function直接调用ProcessData()了.
原先的关系(tag_id -> processing_function)是通过查表来定的, 说明没什么规律;
所以你现在仍然还得查表. 现在这个新的关系(tag_id -> object of T)可以通过如下
的generator function来定:
template
class_base* new_object()
{
return new T;
}
typedef class_base* (*ObjectGenerator)();
然后定义一个表格
vector generator_table;
/* or you can use map generator_map; */
generator_table = {new_object, new_object /* .... */ };

..

【在 g***l 的大作中提到】
: 一个模块,原先是在C中写的,现在要用C++重新写,因为要添加新的功能。
: 情况是如下:
: 程序运行中,能够拿到一段数据,存在连续的memory中,uint8_t *data={30,23,.....
: ...},data[1]用来当tag_id用,不同tag_id要调用不同对象的处理函数,data[2]是表
: 示数据的长度。
: 在原来的C中,我是建立了一个 function pointer look up table,用data[1]来搜索,
: 返回相应的function pointer : void(*pfunc)(uint8_t* in_data_p,uint8_t * out_
: result_p).
: 在C++中,现在每个对象都是一个单独的class,从base class继承来的。
: class base_class

avatar
S*s
19
6park.com 也有。

【在 n***t 的大作中提到】
: good site, thanks
avatar
g*l
20
对,就是需要根据tag_id来查表生成一个相应的对象。
非常感谢。我来试一试。

【在 t****t 的大作中提到】
: 如果我没看错的话, 你的问题不在于决定T的类型, 而是如何从tag_id产生一个T的对象
: . 有了T的对象, 你就可以用virtual function直接调用ProcessData()了.
: 原先的关系(tag_id -> processing_function)是通过查表来定的, 说明没什么规律;
: 所以你现在仍然还得查表. 现在这个新的关系(tag_id -> object of T)可以通过如下
: 的generator function来定:
: template
: class_base* new_object()
: {
: return new T;
: }

avatar
t*o
21
剧情安排两娃就得稍微慢节奏一点。前两季这夫妻俩出任务的频率也太高了。

【在 s****t 的大作中提到】
: 最新这一季故事发展太慢,明显进入鸡肋节奏
avatar
g*l
22
老大的这个方法是可行的。可是又出现新的问题了。
我定义了如下接口:
template
dec_base* new_object()
{
return new T;
}
typedef dec_base* (*ObjectGenerator)();
static std::map generator_map;
template
void register_dec_handle(int tag_id)
{
generator_map.insert(make_pair(tag_id,new_object));
}
如果把以上代码跟 main() 代码放在一个main.cpp里面,编译链接都没有问题。但是如
果把以上代码放在另外一个单独的sample.cpp里面,在另外一个main.cpp中的main()调用
register_dec_handle()的时间,gcc就会报告
g++ main.cpp sample.cpp -o sample.exe
main.cpp: 在函数‘int main()’中:
main.cpp:21:11: 错误:‘generator_map’在此作用域中尚未声明
make: *** [all] Error 1
这事怎么回事? generator_map是在sample.cpp中定义的static变量,通过register_
dec_handle()来操作的。
/////////////////////main.cpp
#include
#include
#include
#include "sample.hpp"
using namespace std;
int main()
{
char data[]="this a test string";
#if 1
register_dec_handle(1);
register_dec_handle(2);

std::map::const_iterator itr;
for(itr=generator_map.begin();itr!=generator_map.end();itr++)
{
cout<first<ObjectGenerator func=itr->second;
dec_base* obj=(*func)();
obj->ProcessData(data);
}
#endif
return 0;
}
/////////////////sample.cpp
#include
#include
#include
#include "sample.hpp"
using namespace std;
dec_base::
dec_base()
{}
dec_base::
~dec_base()
{}
void dec_base::
ProcessData(char * in_data_p)
{
cout<}
dec_1::
dec_1()
{}
dec_1::
~dec_1()
{}
void dec_1::
ProcessData(char* in_data_p)
{
cout<}
bool dec_1::
export_data()
{
cout<}
dec_2::
dec_2()
{}
dec_2::
~dec_2()
{}
void dec_2::
ProcessData(char* in_data_p)
{
cout<}
bool dec_2::
export_data_html()
{
cout<}
template
dec_base* new_object()
{
return new T;
}
typedef dec_base* (*ObjectGenerator)();
std::map generator_map;
template
void register_dec_handle(int tag_id)
{
generator_map.insert(make_pair(tag_id,new_object));
}
////////////////sample.hpp
#ifndef WORK_SAMPLE_H
#define WORK_SAMPLE_H
#include
#include
class dec_base
{
public:
int tag_id;
std::vector result;

public:
dec_base();
~dec_base();
virtual void ProcessData(char* in_data_p);
};
class dec_1:public dec_base
{
private:
int size;
public:
dec_1();
~dec_1();
virtual void ProcessData(char* in_data_p);
bool export_data();
};
class dec_2:public dec_base
{
private:
int range;
public:
dec_2();
~dec_2();
virtual void ProcessData(char* in_data_p);
bool export_data_html();
};
////////////interface
template
dec_base* new_object();
typedef dec_base* (*ObjectGenerator)();
template
void register_dec_handle(int tag_id);
#endif

【在 t****t 的大作中提到】
: 如果我没看错的话, 你的问题不在于决定T的类型, 而是如何从tag_id产生一个T的对象
: . 有了T的对象, 你就可以用virtual function直接调用ProcessData()了.
: 原先的关系(tag_id -> processing_function)是通过查表来定的, 说明没什么规律;
: 所以你现在仍然还得查表. 现在这个新的关系(tag_id -> object of T)可以通过如下
: 的generator function来定:
: template
: class_base* new_object()
: {
: return new T;
: }

avatar
p*o
23
You can have a non-template register_dec_handle function
(taking two paramters tag_id and ObjectGenerator) that
access generator_map directly and the template register_dec_handle
function should call that non-template one. Otherwise,
when the compiler instantiates the function template,
they need to see everything in the current translation
unit, which is obviously not possible here since generator_map
is static.
In short, if you know what is singleton, generator_map
should be one.

调用
对象
律;
如下

【在 g***l 的大作中提到】
: 老大的这个方法是可行的。可是又出现新的问题了。
: 我定义了如下接口:
: template
: dec_base* new_object()
: {
: return new T;
: }
: typedef dec_base* (*ObjectGenerator)();
: static std::map generator_map;
: template

avatar
g*l
24
generator_map不能放到sample.hpp里面去吧?

有.

【在 t****t 的大作中提到】
: 如果我没看错的话, 你的问题不在于决定T的类型, 而是如何从tag_id产生一个T的对象
: . 有了T的对象, 你就可以用virtual function直接调用ProcessData()了.
: 原先的关系(tag_id -> processing_function)是通过查表来定的, 说明没什么规律;
: 所以你现在仍然还得查表. 现在这个新的关系(tag_id -> object of T)可以通过如下
: 的generator function来定:
: template
: class_base* new_object()
: {
: return new T;
: }

avatar
t*t
25
简单的回答: 你需要让register_dec_handle看到generator_map.
换句话说, 生成register_dec_handle的compilation unit需要能看到generator_map.
而register_dec_handle是一个模板, 你用的隐式生成(implicit instantiation)所以
调用者, 即main()需要能看到generator_map.
从另一方面来说, generator_map反正需要经常被查询, 所以应该能被所有查询者看到.
所以声明成static没什么意义. file-scope static的作用是防止名污染, 你这个不在
此列.
长的回答:
这个和我自己的一个程序很类似, 所以我多说两句.
如果是我做, 我会把实现和调用完全分开. 这样分割:
*** base.h: 基类, 只留基类的基本接口和小的inline实现; factory声明, 给定ID产
生类. 这个文件是实现和调用唯一公用的部分.
class base_class { ... };
base_class* decoder_factory(uint_8 ID);
*** base_private.h: include "base.h", 加所有子类的公共声明, 和表格的生成器.
比如
template class decoder;
typedef base_class* (*Generator)();
template base_class* generator() { return new decoder; }
extern map map_generator;
template inline void register_myself() {
map_generator.insert(make_pair(ID, generator));
}
*** base.cpp:基类的实现, 和map_generator的定义, factory的定义
*** dec_1.cpp: include "base_private.h", 加decoder<1>的定义. 比如
template <>
class decoder<1> : public base { .... };
static int dummy = register_myself<1>(), 0;
当然我这是举个例子, 具体的实现还要改, 比如用一个singleton来把以上的都包装成
一个大的factory(不一定是好事); 比如说子类根本不必要是模板; 等等.
这个设计的关键是不仅实现和使用是分开的, 每个实现也都完全相互独立(除了必须遵
守基类的规范以外). 你写一个实现就是一个实现, 不需要到任何公共的地方登记它.
不过, 以上的程序有个毛病, 所有的register_myself都要等map_generator初始化以后
才能用. 所以我自己是把map_generator包装在一个singleton里的, 调用到必然已经初
始化好了.

【在 g***l 的大作中提到】
: 老大的这个方法是可行的。可是又出现新的问题了。
: 我定义了如下接口:
: template
: dec_base* new_object()
: {
: return new T;
: }
: typedef dec_base* (*ObjectGenerator)();
: static std::map generator_map;
: template

avatar
t*t
26
make it extern (declaration only). see my previous post.

【在 g***l 的大作中提到】
: generator_map不能放到sample.hpp里面去吧?
:
: 有.

avatar
g*l
27
非常感谢!
"所有的register_myself都要等map_generator初始化以后才能用" ??
如果把map_generator设成global的话,这个在compile的时间就已经初始化了,为什么
吗还要等待? 还是要注意初始化的顺序问题?

到.

【在 t****t 的大作中提到】
: 简单的回答: 你需要让register_dec_handle看到generator_map.
: 换句话说, 生成register_dec_handle的compilation unit需要能看到generator_map.
: 而register_dec_handle是一个模板, 你用的隐式生成(implicit instantiation)所以
: 调用者, 即main()需要能看到generator_map.
: 从另一方面来说, generator_map反正需要经常被查询, 所以应该能被所有查询者看到.
: 所以声明成static没什么意义. file-scope static的作用是防止名污染, 你这个不在
: 此列.
: 长的回答:
: 这个和我自己的一个程序很类似, 所以我多说两句.
: 如果是我做, 我会把实现和调用完全分开. 这样分割:

avatar
g*l
28
好像这样也不行。
我在sample.cpp里面定义了std::map generator_map;
然后在sample.hpp里面声明extern std::map generator_map;
最后编译的时间会报错: undefined reference :void register_dec_handle(int)

【在 t****t 的大作中提到】
: make it extern (declaration only). see my previous post.
avatar
t*t
29
in c++, except POD types, there is no "compile-time" initialization. almost
all constructors are executed runtime. so the initialization order is
important.

【在 g***l 的大作中提到】
: 非常感谢!
: "所有的register_myself都要等map_generator初始化以后才能用" ??
: 如果把map_generator设成global的话,这个在compile的时间就已经初始化了,为什么
: 吗还要等待? 还是要注意初始化的顺序问题?
:
: 到.

avatar
t*t
30
OK, you need some c++ 101. obviously undefined reference of "register_dec_
handle" has nothing to do with definition/declaration of generator_map.

map;

【在 g***l 的大作中提到】
: 好像这样也不行。
: 我在sample.cpp里面定义了std::map generator_map;
: 然后在sample.hpp里面声明extern std::map generator_map;
: 最后编译的时间会报错: undefined reference :void register_dec_handle(int)

avatar
g*l
31
this is the complete error message. I think it is still related to function
template.
template
void register_dec_handle(int tag_id);
was declared in sample.hpp and was implemented in sample.cpp.
both class dec_1 and class dec_2 were declared in sample.hpp and implemented
in sample.cpp.
In main.cpp, #include "sample.hpp", refer to above code.
////////////////////////////////////
$g++ main.cpp sample.cpp sample.hpp -o sample
/tmp/ccPFwZuH.o: In function `main':
main.cpp:(.text+0x3f): undefined reference to `void register_dec_handle1>(int)'
main.cpp:(.text+0x4b): undefined reference to `void register_dec_handle2>(int)'
collect2: ld returned 1 exit status

【在 t****t 的大作中提到】
: OK, you need some c++ 101. obviously undefined reference of "register_dec_
: handle" has nothing to do with definition/declaration of generator_map.
:
: map;

avatar
g*l
32
hehe. got it resolved.
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13
it is the same issue as the generator due to template.
Anyway, thank you so much!

【在 t****t 的大作中提到】
: OK, you need some c++ 101. obviously undefined reference of "register_dec_
: handle" has nothing to do with definition/declaration of generator_map.
:
: map;

avatar
b*i
33
我提醒你一下,template register_dec+handle(int tag_id)具体编译的时
候对某个类是否展开并放进obj,取决于那个类型是否在该cpp中被用到。编译时候没看
见,比如dec_1没出现,就不在obj,自然链接看不见。
所以,你前面还是没有说清楚。你提到的要用简单的表达式生成某个类型的一个实例,
是纯粹运行时才知道的,在编译时根本不知道。这就好像你在写一个编译器,在后期扩
展新类型的时候,不需要更改已有的架构。
所以你可以回到第一个方案,就是利用虚函数来实现。
那么,每个新类型register的时候把一个整数的值和自己类里面的函数的实现登记。这
个函数要extern "C",这个函数在这个类cpp里面生成这个类的一个实例。这样,一个
函数createAnInstance(int tag_id)里面{ base * A=getyourfunction, A->
createInstance();}就实现了生成这个类的实例这个过程。而登记类生成函数分布在
每个类自己的文件中。
另外,有人提到宏,借助一个宏,如果把tag_id变string,自己好好写个宏,可以写
create(int, x) 等价于 int x = createAnInstance("int");
具体还有很多要说的,但是你要的东西是可做的,也不难。但要搞清楚编译和链接的过
程。

function
implemented

【在 g***l 的大作中提到】
: this is the complete error message. I think it is still related to function
: template.
: template
: void register_dec_handle(int tag_id);
: was declared in sample.hpp and was implemented in sample.cpp.
: both class dec_1 and class dec_2 were declared in sample.hpp and implemented
: in sample.cpp.
: In main.cpp, #include "sample.hpp", refer to above code.
: ////////////////////////////////////
: $g++ main.cpp sample.cpp sample.hpp -o sample

avatar
g*l
34
谢谢。还要谢谢thrust.
template的东西我以前基本没有怎么用过,很多东西不知道。这两天为了解决这个问题
,基本都在看资料学习,知道了不少东西。
我原先认为compiler在翻译template的时间,只是做个标记,等到最后链接的时间再去
obj里面找。
现在的选择要么是写一个专门的singleton,这个是来代替前面的global generator. 要
么就是回到你说的那种,类似于C里面的function Pointer LUT。

【在 b***i 的大作中提到】
: 我提醒你一下,template register_dec+handle(int tag_id)具体编译的时
: 候对某个类是否展开并放进obj,取决于那个类型是否在该cpp中被用到。编译时候没看
: 见,比如dec_1没出现,就不在obj,自然链接看不见。
: 所以,你前面还是没有说清楚。你提到的要用简单的表达式生成某个类型的一个实例,
: 是纯粹运行时才知道的,在编译时根本不知道。这就好像你在写一个编译器,在后期扩
: 展新类型的时候,不需要更改已有的架构。
: 所以你可以回到第一个方案,就是利用虚函数来实现。
: 那么,每个新类型register的时候把一个整数的值和自己类里面的函数的实现登记。这
: 个函数要extern "C",这个函数在这个类cpp里面生成这个类的一个实例。这样,一个
: 函数createAnInstance(int tag_id)里面{ base * A=getyourfunction, A->

avatar
t*t
35
我那个方案的接口仍然是虚函数, 但是factory用的是模板. 按照我的方案, 在每个类
文件里会使用一次register_myself用来调用map.insert(..., generator),
而generator又会调用new decoder从而instantiate整个类. 这个过程对使用
者完全是不可见的, 使用者能看到的是两个东西: 一个是虚函数的接口, 定义在base_
class里, 另一个是decoder_factory, 它查找map调用相应的generator(已生成)返
回正确的对象.
这一套pattern我自己在用, 所以我很清楚它一定会work:)

【在 b***i 的大作中提到】
: 我提醒你一下,template register_dec+handle(int tag_id)具体编译的时
: 候对某个类是否展开并放进obj,取决于那个类型是否在该cpp中被用到。编译时候没看
: 见,比如dec_1没出现,就不在obj,自然链接看不见。
: 所以,你前面还是没有说清楚。你提到的要用简单的表达式生成某个类型的一个实例,
: 是纯粹运行时才知道的,在编译时根本不知道。这就好像你在写一个编译器,在后期扩
: 展新类型的时候,不需要更改已有的架构。
: 所以你可以回到第一个方案,就是利用虚函数来实现。
: 那么,每个新类型register的时候把一个整数的值和自己类里面的函数的实现登记。这
: 个函数要extern "C",这个函数在这个类cpp里面生成这个类的一个实例。这样,一个
: 函数createAnInstance(int tag_id)里面{ base * A=getyourfunction, A->

avatar
b*i
36
刚要睡觉,突然想起来,.hpp要声明templateregister_dec,在每个类的cpp中
要实现这个类型的register_dec,比如dec_1, dec_2,你是不是忘了实现了?我知道你
在sample.cpp里面定义 了两个类,这两个类的register_dec要定义(实现)。你先看
看这样做能否通过。
这样每个类自己编译的时候要看到那个.h,就展开那个类的template,就可以把这个类
型的实现的编译结果放在自己的obj里面。

【在 g***l 的大作中提到】
: 谢谢。还要谢谢thrust.
: template的东西我以前基本没有怎么用过,很多东西不知道。这两天为了解决这个问题
: ,基本都在看资料学习,知道了不少东西。
: 我原先认为compiler在翻译template的时间,只是做个标记,等到最后链接的时间再去
: obj里面找。
: 现在的选择要么是写一个专门的singleton,这个是来代替前面的global generator. 要
: 么就是回到你说的那种,类似于C里面的function Pointer LUT。

avatar
t*t
37
that's exactly my pattern.

【在 b***i 的大作中提到】
: 刚要睡觉,突然想起来,.hpp要声明templateregister_dec,在每个类的cpp中
: 要实现这个类型的register_dec,比如dec_1, dec_2,你是不是忘了实现了?我知道你
: 在sample.cpp里面定义 了两个类,这两个类的register_dec要定义(实现)。你先看
: 看这样做能否通过。
: 这样每个类自己编译的时候要看到那个.h,就展开那个类的template,就可以把这个类
: 型的实现的编译结果放在自己的obj里面。

avatar
t*t
38

you may choose to do so, if you know exactly what parameter you use,
which is true in your case. in this case, you can hide implementation and
only provide declaration. in fact in your case, you don't even have to
provide
declaration, you can only provide the declaration of base class.
client don't have to know what subclass you implemented.

【在 g***l 的大作中提到】
: 谢谢。还要谢谢thrust.
: template的东西我以前基本没有怎么用过,很多东西不知道。这两天为了解决这个问题
: ,基本都在看资料学习,知道了不少东西。
: 我原先认为compiler在翻译template的时间,只是做个标记,等到最后链接的时间再去
: obj里面找。
: 现在的选择要么是写一个专门的singleton,这个是来代替前面的global generator. 要
: 么就是回到你说的那种,类似于C里面的function Pointer LUT。

avatar
g*l
39
对,我在sample.cpp里面加上了这两个函数的声明就可以编译通过了。
template void register_dec_handle(int);

template void register_dec_handle(int)

【在 b***i 的大作中提到】
: 刚要睡觉,突然想起来,.hpp要声明templateregister_dec,在每个类的cpp中
: 要实现这个类型的register_dec,比如dec_1, dec_2,你是不是忘了实现了?我知道你
: 在sample.cpp里面定义 了两个类,这两个类的register_dec要定义(实现)。你先看
: 看这样做能否通过。
: 这样每个类自己编译的时候要看到那个.h,就展开那个类的template,就可以把这个类
: 型的实现的编译结果放在自己的obj里面。

avatar
g*l
40
yes, the client only know the base class.
even in old C code, the client know nothing about the details of the decoder
at all.

【在 t****t 的大作中提到】
:
: you may choose to do so, if you know exactly what parameter you use,
: which is true in your case. in this case, you can hide implementation and
: only provide declaration. in fact in your case, you don't even have to
: provide
: declaration, you can only provide the declaration of base class.
: client don't have to know what subclass you implemented.

avatar
b*i
41
glad to know!
are you writing compiler? Like a matlab?

【在 g***l 的大作中提到】
: 对,我在sample.cpp里面加上了这两个函数的声明就可以编译通过了。
: template void register_dec_handle(int);
: 和
: template void register_dec_handle(int)

avatar
t*t
42
obviously it's a serdes...

【在 b***i 的大作中提到】
: glad to know!
: are you writing compiler? Like a matlab?

相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。