免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3435 | 回复: 15
打印 上一主题 下一主题

[C++] 这段代码符合C++标准吗? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-07-17 14:36 |只看该作者 |倒序浏览
贴出相关部分的代码,
template <class T>
class TypeMessage {
    static vector<class Handler*> registry;
public:
    class Handler {
    public:
        Handler() { }
        virtual void handleEvent(const T* t) = 0;
    };
};

class On : public TypeMessage<On> {
    string comment;
public:
    On(string str) { comment = str; }
};


class Off : public TypeMessage<Off> {
    string comment;
public:
   Off( string str ) { comment = str; }
};

vector<TypeMessage<On>::Handler*> TypeMessage<On>::registry;
vector<TypeMessage<Off>::Handler*> TypeMessage<Off>::registry;

...
在VC8下编译,报错提示最后两个registry定义重复,在gcc下编译通过。
请问,这两个registry的定义是否符合C++标准?

论坛徽章:
0
2 [报告]
发表于 2008-07-17 18:22 |只看该作者
是正确的
应该是VC8处理有问题,我在VC9中测了一下,也没问题

论坛徽章:
0
3 [报告]
发表于 2008-07-17 18:56 |只看该作者
多谢,在另一个论坛看到的回复是:
template <class T>
class TypeMessage {
     static vector<class Handler*> registry;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Handler相当于在TypeMessage所属的namespace 引入了一个名为Handler的类,而不是你的TypeMessage<T>::Handler。在g++可以编译通过,说明g++的名字查找不标准。


我的理解是,这里的Handler对于VC8编译器来说,和下面的TypeMessage<T>::Handler没有关系,和叫HandlerB一个效果。
而在g++里,把这两者等同了。

论坛徽章:
0
4 [报告]
发表于 2008-07-17 19:11 |只看该作者
原帖由 Elite 于 2008-7-17 18:56 发表
多谢,在另一个论坛看到的回复是:


我的理解是,这里的Handler对于VC8编译器来说,和下面的TypeMessage::Handler没有关系,和叫HandlerB一个效果。
而在g++里,把这两者等同了。

这个回复有点扯了,Handler是内嵌类,怎能说是在TypeMessage所在名字空间引入该类?
另外,对于名字查找规则,只有VC才不遵从参数依赖查找规则(Koenig 查找),说g++的查找规则不标准有点颠倒黑白了

论坛徽章:
0
5 [报告]
发表于 2008-07-17 20:51 |只看该作者
VC8的查找规则不了解,代码在VC9编译也是同样的错误。下面是完整代码。
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. using namespace std;

  5. template <class T>
  6. class TypeMessage {
  7.     static vector<class Handler*> registry;
  8. public:
  9.     class Handler {
  10.     public:
  11.         Handler() { TypeMessage<T>::registerHandler( this ); }
  12.         virtual void handleEvent(const T* t) = 0;
  13.     };
  14.     void notify() {
  15.         for(int i = 0; i < registry.size(); i++)
  16.             registry.at(i)->handleEvent( (T*)this );
  17.     }
  18.     static void registerHandler(Handler* h) { registry.push_back( h ); }
  19. };

  20. class On : public TypeMessage<On> {
  21.     string comment;
  22. public:
  23.     On(string str) { comment = str; }
  24.     void start() const {  cout << "OnEvent.start - " << comment << '\n'; }
  25. };

  26. vector<TypeMessage<On>::Handler*> TypeMessage<On>::registry;

  27. class Off : public TypeMessage<Off> {
  28.     string comment;
  29. public:
  30.    Off( string str ) { comment = str; }
  31.    void stop() const { cout << "OffEvent.stop - " << comment << '\n'; }
  32. };
  33. vector<TypeMessage<Off>::Handler*> TypeMessage<Off>::registry;

  34. class MasterConsole : public On::Handler, public Off::Handler {
  35. public:
  36.     void handleEvent(const On* msg) {
  37.         cout << "MasterConsole - ";
  38.         msg->start();
  39.     }
  40.     void handleEvent(const Off* msg) {
  41.         cout << "MasterConsole - ";
  42.         msg->stop();
  43.     }
  44. };

  45. class PowerMonitor : public On::Handler {
  46.     public:
  47.     void handleEvent(const On* msg){
  48.         cout << "PowerMonitor - ";
  49.         msg->start();
  50.     }
  51. };

  52. int main(){
  53.     MasterConsole mc;
  54.     PowerMonitor pm;
  55.     On oneEvent( " lights " ); Off thrEvent( " elevators " );
  56.     On twoEvent( " hvac " ); Off fouEvent( " frontDoor " );

  57.     oneEvent.notify();
  58.     twoEvent.notify();
  59.     thrEvent.notify();
  60.     fouEvent.notify();

  61.     return 0;
  62. }
复制代码

论坛徽章:
0
6 [报告]
发表于 2008-07-17 23:13 |只看该作者
vector<TypeMessage<On>::Handler*> TypeMessage<On>::registry;
vector<TypeMessage<Off>::Handler*> TypeMessage<Off>::registry;

----------------------------------------------------------------------------------------

这两句没看明白,lz能解释下么

论坛徽章:
0
7 [报告]
发表于 2008-07-17 23:24 |只看该作者
对了,LZ,你是用什么版本的GCC编译的,我编译通不过

另外,你应该类似地如下定义你的模板类TypeMessage:

  1. template <class T>
  2. class TypeMessage {
  3. public:
  4.     class Handler {
  5.     public:
  6.         Handler() { TypeMessage<T>::registerHandler( this ); }
  7.         virtual void handleEvent(const T* t) = 0;
  8.     };
  9.     void notify() {
  10.         for(int i = 0; i < registry.size(); i++)
  11.             registry.at(i)->handleEvent( (T*)this );
  12.     }
  13.     static void registerHandler(Handler* h) { registry.push_back( h ); }

  14. private:
  15.     static vector<Handler*> registry;
  16. };

  17. template <typename T>
  18. vector<typename TypeMessage<T>::Handler*> TypeMessage<T>::registry;
复制代码

其一,在Handler定义后定义静态成员registry,也可以通过在原程序中定义之前显示声明Handler类,此时Handler才是类中嵌套类
其二,对模板类静态成员的定义应该如上代码所示,当然你也可以显示特化它们(事实上这是编译器做的工作),比如,针对你的代码进行修改:

  1. template<>
  2. vector<TypeMessage<On>::Handler*> TypeMessage<On>::registry;

  3. template<>
  4. vector<TypeMessage<Off>::Handler*> TypeMessage<Off>::registry;
复制代码

[ 本帖最后由 tyc611 于 2008-7-17 23:27 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2008-07-17 23:34 |只看该作者
ls的兄弟能解释下么?

vector<TypeMessage<On>::Handler*> TypeMessage<On>::registry;

这样写是什么意思呢?真的没有语法错误吗?
前面是一个具体具化的vector,后面跟的是不同类型一个静态的成员变量

想不明白

[ 本帖最后由 void_while 于 2008-7-17 23:36 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2008-07-17 23:38 |只看该作者

回复 #7 tyc611 的帖子

另外,测试了一下,在GCC中利用特化方式是不能通过连接的

论坛徽章:
0
10 [报告]
发表于 2008-07-17 23:42 |只看该作者
原帖由 void_while 于 2008-7-17 23:34 发表
ls的兄弟能解释下么?

vector TypeMessage::registry;

这样写是什么意思呢?真的没有语法错误吗?
前面是一个具体具化的vector,后面跟的是不同类型一个静态的成员变量

想不明白

本来应该是

  1. template <typename T>
  2. vector<typename TypeMessage<T>::Handler*> TypeMessage<T>::registry;
复制代码

它的代码相当于用On和Off两个类型去特化上面类模板的这个成员,语言标准是否允许这样做我也不清楚,关于模板规则太复杂了,也很难写得具有较好的移植性
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP