精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-11-12
最后修改:2010-11-25
请问怎么把这贴子转去问答区或是入门讨论? 以前的贴子自己理解有误,觉得没啥可问的,就删除重写了,新手要个"前车之鉴"的,就看一下1,8楼好了. 不讨论"用try-catch处理异常好,还是用error code好"只是问怎么在C++中用好try-catch 现在大部分的C++异常处理都是用error code判断返回值 比如下面的代码,就是我在公司看到的,还有更多的GOTO的就不举例了. ERROR SomeFunc3() { //... do { // ... eRet = DoSomeThing1(); if (ERR_NONE != eRet) { break; } eRet = DoSomeThing2(); if (ERR_NONE != eRet) { break; } // more code like above }while(false) // release memory, handle or something. return eRet; } 如果用JAVA代码,我可能会这样写 MyBaseException extends RuntimeException MyException1 和 MyException2 extends MyBaseException class Moudle { public void DoSomeThing1() { // ... // 假设连接主机失败 if (expect != value) { throw new MyException1("error context" + value);// 是个 runtime exception } // ... // 假设版本不对 if (expect2 != value2) { throw new MyException2("error context" + value2);// runtime exception } // ... } public void DoSomeThing2() { // ... // 假设连接主机超时 if (expect3 != value3) { throw new MyException1("error context" + value3);// runtime exception } // ... // 假设外部DLL有错 if (expect4 != value4) { throw new MyException2("error context" + value4);// runtime exception } // ... } } //另一个CLASS的方法中 class APILike { public void SomeFun3() { Moudle mm = new Moudle (); try { mm.DoSomeThing1(); mm.DoSomeThing2(); // ... } catch (MyException1 e) { // handle exception 或是不catch这个异常 } catch (MyException2 e) { // handle exception 或是不catch这个异常 } catch (MyBaseException e) { // 把错误发给用户 SendInfoToUI(e.getMessage()); } // ... } } JAVA代码很好理解,异常也很好扩展. 只针对以上JAVA代码,如果在C++中用try-catch要怎么做(能给伪代码吗)?异常体系如何定义?参考了一下MSDN,里面还有__try(好象WINDOWS专用?),更把我搞糊涂了. ============================================================================ 问题2: 有一个32位程序要移植到64位上,我在 WIN XP & VS2005 & 活动解决方案平台x64 上编译出EXE和DLL,COPY到一台WIN2003 x64 的 F:\Program Files (x86)\XXXXXX 下运行. works just fine. 然后我在x64机器上用depends工具(64位版)view了一下DLL,在面版里发现我自己的DLL,cpu显示为x64 ,但是它depend的系统DLL,比如说KERNEL32.DLL是在windows\syswow64下的那个(不明白为啥不是system32下),WINMM.DLL是windows\system32下的, 所有系统DLL CPU显示均为X86. 我知道syswow64是windows-on-windows 64的意思, 里面放的DLL用来兼容32位程序.而system32里是放64位版本的DLL. 然后用depends工具(64位版)view了一下windows\system32\kernel32.dll发现cpu显示为x86...好象所有的系统DLLCPU都是显示x86,难道不应该是x64吗? 我在WINXP(x86)上编译时,link的系统DLL的导入库(比如说winmm.lib wininet.lib)应该都是32位的吧 PS:不讨论"最好最省事的方法是在x64系统的x86 32位虚拟机里面运行32位程序,避免移植到x64的工作量和风险。 "因为还要移植LINUX64. 以前没有做过X86 TO X64, 如果在WIN x64上直接跑32位的程序,会影响性能吗?比如说,字长需要转换的什么 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-11-12
zx339 写道 Hi all,
很担心我正把一个应该归类于"入门讨论"的话题(问题)post在C++区,进一步恶化了"C++区无营养",导致有经验C++ dev更加远离不活跃的C++区.PS:我有2年的C++的工作经验. 问题发现在维护别人代码上.只考滤 windows, VS IDE, 非嵌入式(内存足), 支持多线程 的情况下. 1,const修饰函数内变量. ERRCODE SomeFunc(HANDLE* pHandle) { // ... const char * pStep = pHandle->szStep; // ... } 我可以理解,原作者的意思是防止在接下来的代码里,因为改变pStep而改变了pHandle->szStep,所以给pStep加上了const. (后来又考滤了一下,加了 const 也没用,除非是用char const * pStep) 很简单,可以马上觉得用const修饰函数参数是才比较正确的方法. 此时的pStep指针,应该是在分配常量区的指针吧?应该不会跟随函数栈被收回? 以此推出const修饰函数内变量无意义. 成立吗? 2,函数内定义结构体 ERRCODE SomeFunc2(void *SomePoint) { struct Config { char * a; void * b; int c; } Config cfgDefault[] = { {"aaaa", SomePoint->member1, 11}, // ... something like above. }; // ... some code use cfgDefault } 把结构体定义在函数内会影响效率吗?把结构体定义放在外面的话和现在比,有啥不同?个人觉得写在函数内或外编译后的效果可能是一样的,只是单纯的觉得这样的代码很geek,还是我少见多怪了? 3,异常处理流程 虽然各种教科书都说 goto很evil,但是实际工作中,看到goto身影的机会还是很多. 也许出于历史原因, 版本原因, 程序运行环境原因, <script type="text/javascript" src="http://www.iteye.com/javascripts/tinymce/themes/advanced/langs/zh.js"></script><script type="text/javascript" src="http://www.iteye.com/javascripts/tinymce/plugins/javaeye/langs/zh.js"></script>只能用返回值和GOTO来控制异常处理流程. 以下流程我是真是第一次见识. ERROR SomeFunc3() { //... do { // ... eRet = DoSomeThing1(); if (ERR_NONE != eRet) { break; } eRet = DoSomeThing2(); if (ERR_NONE != eRet) { break; } // more code like above }while(false) // release memory, handle or something. return eRet; } 用try-catch-throw会影响性能,因为要压栈什么的.情问这种影响大吗?可移植性呢? 工作这几年也基本上没看到过用try-catch-throw来处理的,一些书上也只是写个简单用例,有好一点的资料吗? 2. 结构体在函数里是为了定义私有的结构体,仅供本函数使用吧,从阅读上也方便,不需要上下翻找。 3. Java是一定要处理异常,C#不需要强迫处理异常,所以要不要try catch取决于程序员。 design by contract里有个很有意思的话题,什么时候是异常,什么时候是错误。 |
|
返回顶楼 | |
发表时间:2010-11-20
最后修改:2010-11-20
1.关于const,char const * pStep 和 const char * pStep是一回事,在你的函数里,想表示szStep指向一个不可改变的内存。作者这么写有两个原因,不写const,你编译不过,因为pHandle->szStep返回的是const,没有类型转换,编译不过(希望你的是正常的编译器和警告等级);第二,想防止对指向内存作修改。
2.函数体内定义局部结构体或类,只是表示该类的作用域在函数内,相当于函数的一个助手,放在外边,扩大了作用域,区别明显吧? 3.try-catch-throw之类的性能不用考虑,估计影响不大。但在c++大型项目中,和JAVA不一样,c++由于返回值(多值输出),全局变量的存在,状态的表示即使在跨层下,也不一定非得用异常,也许基于网络的应用会定义一套异常继承结构(我没做过,PS异常体系不好定义),异常的加入还会使多人的并发开发项目变得不容易调试,所以总体上用异常来控制主要的出错逻辑的c++大型项目很少(我没见过)。 PS:可能对于逻辑集中的库中利用异常来控制的还是有的,但对于集合了各种逻辑的应用程序来说,异常来控制真的是很不好控制。 |
|
返回顶楼 | |
发表时间:2010-11-20
GOTO正确使用,用到的也就3个作用
1.出错前打印一下出错信息; 2.表示某个变量值改变后,再重新做一遍操作,一般就是和Label again, retry连用,因为这样比循环可以更好的表示代码意图。 3.跳出多重循环。 你给的例子哪有GOTO? |
|
返回顶楼 | |
发表时间:2010-11-20
最后修改:2010-11-20
贴段代码(摘自netbsdsrc/lib/libc/net/getservent.c:65–104)
again: if ((p = fgets(line, BUFSIZ, servf)) == NULL) return (NULL); if (*p == '#') goto again; cp = strpbrk(p, "#\n"); if (cp == NULL) goto again; *cp = '\0'; [...] return (&serv); |
|
返回顶楼 | |
发表时间:2010-11-21
zx339 写道 Hi all,
用try-catch-throw会影响性能,因为要压栈什么的.情问这种影响大吗?可移植性呢? 工作这几年也基本上没看到过用try-catch-throw来处理的,一些书上也只是写个简单用例,有好一点的资料吗? 好的编译器会尽可能消减这个开销的,不过好像ACE里面放弃了C++异常是因为他搞不清构造函数的行为? 一般如果你知道你的代码有 /0的bug, 那么这个时候用个异常让程序正常跑还是不错的,只要不用于逻辑。 最好的情况就是,用了异常但是没有执行的效率和没用一样。 |
|
返回顶楼 | |
发表时间:2010-11-21
1.const char * pStep和char const * pStep一模一样的,与char*const pStep是不一样的。
2.函数内部类的使用场合是一些类只在一个函数内有用,在函数外无意义。类型应该尽量定义的可见范围更小,好处是修改的时候代价更小。 3.说实话建议不要使用C++的异常机制,尤其在大项目里面。C++可以有多值返回,所以不要将异常当作带额外返回值的手段。 话说你这两年C++基础不是很扎实啊,尤其是第一个问题。 标准C++的类型修饰符是放在类型右侧的,但是为了兼容例如const也可以放在左边。 举个例子: char -> 基础类型 char const -> const 修饰了char,代表不可变的char char const * -> *修饰了char const,代表指向了一个不可变的char const的指针,但是这个指针本身可变。 char const * const -> const 修饰了 char const *,代表这个指针本身也不可变。 char * -> *修饰了char,代表指向了一个可变的char的指针 char* const-> const 修饰了char*,代表了指向一个可变char的不可变指针。 char const是标准写法 const char是兼容写法,与char const等效,不过目前倒是这个比较常见。 其实能正确的使用const,可以很好的体现一个C++程序员的素质。 |
|
返回顶楼 | |
发表时间:2010-11-22
// a is a pointer to int const; const int *a; // a is a const pointer to int; int *const a = &n; // a is a const pointer to int const; const int *const a = &n; |
|
返回顶楼 | |
发表时间:2010-11-24
最后修改:2010-11-25
thinkx 写道 1.const char * pStep和char const * pStep一模一样的,与char*const pStep是不一样的。
2.函数内部类的使用场合是一些类只在一个函数内有用,在函数外无意义。类型应该尽量定义的可见范围更小,好处是修改的时候代价更小。 3.说实话建议不要使用C++的异常机制,尤其在大项目里面。C++可以有多值返回,所以不要将异常当作带额外返回值的手段。 话说你这两年C++基础不是很扎实啊,尤其是第一个问题。 标准C++的类型修饰符是放在类型右侧的,但是为了兼容例如const也可以放在左边。 举个例子: char -> 基础类型 char const -> const 修饰了char,代表不可变的char char const * -> *修饰了char const,代表指向了一个不可变的char const的指针,但是这个指针本身可变。 char const * const -> const 修饰了 char const *,代表这个指针本身也不可变。 char * -> *修饰了char,代表指向了一个可变的char的指针 char* const-> const 修饰了char*,代表了指向一个可变char的不可变指针。 char const是标准写法 const char是兼容写法,与char const等效,不过目前倒是这个比较常见。 其实能正确的使用const,可以很好的体现一个C++程序员的素质。 thanks for reply. 事情是这样的,当时看别人一个函数的源代码开头有以下两句: const int n = pHandle->unSize; const char * pStep = pHandle->szStep; // some code use n and pStep 函数原型大概是这样: void SomeFun(HANDLD * pHandle); 我当时觉得加const 来修饰没啥用, 整型是直接赋值了,没用;const char* 的话,参数const HANDLD* pHandle就行了. 函数里面用const不好,所以贴出来问一下. char const * 和 const char *是一回事这点我搞忘了,这个丢人了. 看代码时把const char * p当时理解成 char * const p了, 因为后者可以 p[2] = 'a';而改变内容. 所以当时觉得const修饰函数内变量无意义. 然后又看到一段代码,一个函数内部定义了类,我当时想,嵌套类不就好了么,非写在函数里干嘛?所以又拿出来问了一下. 现在觉得自己有点偏执,有点一根经, const Iterator自己也用得不少, 函数内部定义的类,编译器也会优化, 所以贴子1,2两点的讨论完全没啥意义,我就删除掉了,只问一下C++中的异常写法和我新加的一个64位迁移的问题. |
|
返回顶楼 | |
发表时间:2010-11-25
最后修改:2010-11-25
1.char * const 和 const char *不是一回事。const出现在*的左边是一回事,const出现在*的右边是一回事。
2.c++中加异常和JAVA加异常语法是差不多的,你可以选择继承std下的exception, bad_cast, runtime_error, logic_error, bad_alloc等类。不过c++异常要比java异常考虑的东西要多,你得将自己定义的异常定义virtual虚构函数,你得将异常所在函数前面将堆上的资源或其他资源自己释放,所以你必须得考虑用智能指针改写前面的代码,另外,如果是非runtime_error的异常,你将改变函数的签名,c++中由于函数指针的存在,宏等其他一些用法,并且你的项目恰好用到了这些,你添加异常到函数接口带来的可能出错的机会是很大的。 3.x86转换到64位,其实就是windonws将中间添加了一个转换层,这个转换层截取一些函数调用,并将其恰当的粘合到win64上,但是这个转换层是工作在用户态的,所以如果你写驱动程序(内核),那你就得重写了(这个不介绍,很多内容)。估计你不是写驱动程序的,所以你只要测试一下在64下的程序即可。另外,你不要考虑性能,添加转换层将你的类型转换为64位类型,是必然需要性能损耗的,相信你也不是写性能敏感的程序的,如果性能无法接受,再考虑重写。 |
|
返回顶楼 | |