好。
还不知道dynamic_cast<void*>()能转换成真实类型的指针。有这个功能,真太好了。
等C++0x出来后,就可以用:
auto pv = dynamic_cast<void*>(...)来获取真实类型了。
感觉上,
C/C++象是蓝领,.NET/Java象是白领
C/C++象是做苦力,.NET/Java象是Office
re: 为什么main有多种格式? 沐枫 2006-06-09 09:13
cdecl调用规范是c语言特有的。
例如有函数: int f(int,...)
r = f(a1,a2,a3,a4)
它动作如下:
1. 调用方,先把参数按从后面到前面的顺序压栈。
--> 为什么这么做?为了实现可变参数。特别是为main和printf所做的工作。
.... 如上面的f,在调用时按a4,a3,a2,a1顺序压栈。即使参数无数个,也不会影响函数的实现。
2. 调用方,负责清理栈空间
--> 为什么这么做?因为到底压了多少个参数在栈里头,只有调用方才知道。
3. 返回值,一概放到规定的寄存器中。
--> 为什么这么做?这样可以允许不使用返回值,寄存器不占用存储空间,不用关心内存资源问题。
小结:使用了cdecl,c语言就可以只关心函数名,而不再关心参数个数,参数类型,函数的返回值问题。因此,一个函数名,仅仅表示了函数的入口,而c语言中的函数原型,仅仅是为了让编译器生成相应的调用代码。
因此,对于一个函数而言,函数原型,爱怎么定义就怎么定义,编译器和链接器都不会怪你;后果就是,如果原型定义有问题,运行结果要么是错的,要么程序甚至系统崩溃。
课后提问:在C中,能否返回结构体呢?
re: Google为什么会被封锁? 沐枫 2006-06-01 08:58
gmail我还一直在用啊。什么时候有封过,我怎么不知道?
re: resource dll 沐枫 2006-05-25 13:42
这个模板把内容都遮住了。
另外,对于楼主的例子,还是不要有返回值的好。因为这容易引起误用。函数的用户常常会以为SetName返回的是未设置以前的值,而不是错误与否。
re: 指针数组和数组指针 沐枫 2006-05-22 09:18
其实,C/C++等编程语言之所以难懂,是因为,中国人特别是有点文化的人,素来喜欢用简化语。
就象某年春晚相声中,将简化语大做批判,其中“上海吊车厂的人员”简称为“上吊的”一样。
指针数组和数组指针,简化的象术语一样。C/C++本来就没有那么多的术语,人为增加术语,只会使C/C++更加晦涩难懂。
直接称呼全称,估计问题就解决了:
用于存储指针的数组、指向数组的指针
re: 把代码移植成UNICODE 沐枫 2006-05-19 09:47
狂晕。看了半天,来了一句“失败”!!!
从目前来看,用异常,在OOP方面已经很普遍了。
它对于栈展开,对象自我析构,和资源管理方面可以做得很好。
另外,在C++中,应使用bool代替BOOL。
AJAX(Asynchronous JavaScript and XML)的名字已经对这些东西说的很明白了。
AJAX在技术方面并非新东西,而是将近几年的技术做一个总结。
因此,虽说有炒作,但更多的是,对用户体验的重视。
re: 母亲节快到了,写点东西送给母亲 沐枫 2006-05-12 16:57
看了很感动。
眼看着你就毕业了,我想两年内,你们的家就会因为你的奋斗而更加的幸福。
正想说呢,结果被楼上先说了。:)
看来M$的宣传到位啊。这么多难用的方法(最后一个还算不错),楼主都知道了,就是不知道标准C库的方法。
C++并不能带来更多的效率。主要还是程序(员)本身。
@万连文
低端嵌入式,还是汇编和C。
中端嵌入式,是C和C++。
高端的,一般是C/C++,Java,.NET。
@christanxw
并非如此。
传奇是delphi,许多小游戏是javaApplet和Flash,已经有.NET和Java的大型游戏和网络游戏。手机游戏相当多是用.NET和Java,一部份用C++。
另外,C/C++做的游戏也需要脚本。
越往后,C/C++做游戏的优势也越小。
估计遇到这样的for语句,在某些大公司是会被警告直至走人的。
干嘛非要放到括号里完成呢?
另外,字符数组你这程序是不能用的。
我给你一个测试用例:
char arr[5] = {'H', 'e', 'l', 'l', 'o'};
----------
BTW,你如果要指定是C++,那么,C++中已经有reverse函数(头文件algorithm):
reverse(str, str+strlen(str)-1);
而交换变量,也有swap函数(头文件algorithm):
swap(*head++, *tail--);
re: Is it a vc6 bug? 沐枫 2006-04-25 08:58
这个语句,无论如何都不能说是编译器的bug。
根据编译器实现的不同,可以有不同的结果。
特别是优化过以后,有可能先执行 b=a,再执行 (a+b)-b。这是最优化的。
当然也可能是先执行(a+b),再执行 (b=a),再执行 (a+b)-b。
规则:在同一条语句中不要让发生改变的变量出现多次。
re: 我们为何从不参与? 沐枫 2006-04-24 11:29
和能力无关。
一是拿来主义
二是英文不好
char* revstr(char* str){
char* head = str;
char* tail = head + strlen(head) -1;
while(head < tail) {
char c = *head;
*head++ = *tail;
*tail-- = c;
}
return str;
}
代码风格应该受到批评。
就这么几行的程序,就让人看得难以理解--特别是那个恐怖的for.
而且就本程序来说,没必要另外分配一个内存。
BTW: //Feature: This version is suitable for both sring and array
这个更离谱了,string还好说,array如何能用呢?
参考小文:
http://ly4cn.cnblogs.com/archive/2006/04/06/368210.html
里面的MASM是6.14,不知道vc6带的是不是这个版本?(可以dos下打入ml 查看)。
如果是的话,就可以在嵌入汇编中使用文中的api定义和调用了。
这就非常方便。
你那是C语言。只不过是把malloc用new来替代罢了。
真正的C语言(C99)是支持动态数组的,如:
void func(int N)
{
int arr[N][N] = {0};
...
}
对于C++来说,则:
void func(int N)
{
vector<vector<int> > arr(N);
for_each(arr.begin(), arr.end(), bind2nd(mem_fun_ref(&vector<int>::resize), N));
...
}
re: 幻方,呵呵学习学习 沐枫 2006-04-10 09:03
int ** arr = new int * [N];
for (i = 0 ;i < N;i ++ )
arr[i] = new int [N];
for (i = 0 ;i < N;i ++ )
for (j = 0 ;j < N;j ++ )
arr[i][j] = 0 ;
好可怕的数据结构和初始化!!!
re: 对MFC8.1的白日梦 沐枫 2006-04-10 08:47
MS多少年没有对mfc的结构做大的变动了?再加上现在的重点是放在.NET以及新一代的应用程序框架上(这里要骂一句,好象新的框架只能用在vista上),估计MFC即使升到9.0也仍然是修修补补。没戏。
re: 能生成这个类的一个对象嘛??? 沐枫 2006-04-06 14:20
2005也不行。
因为无论如何都不知道如何给出一个int的值。
从这一点来说,gcc不知道会把damn实例化成什么,damn<0>吗?
"通过使操作系统更安全、更可靠、响应更及时,使人们更自信 "
更安全可靠不去评论。
响应更及时,估计要靠硬件来支持,从这一点来说,这不是MS的功劳,而应该是钱包的功劳吧。也正因为是钱包的功劳,所以人们才更自信。。。
我没看到onsize,只看到oncreate,是不是楼主写错了?
re: 一段关于memcpy的代码 沐枫 2006-04-01 09:46
个人觉得很难优化。因为每个字节拷贝,都要留一个跳转入口。编译器又怎么敢私自用8字节操作指令直接优化掉它呢。
由此估计,写此代码纯粹是为了挑战C/C++的语法。
re: C#中重用c/c++旧模块 沐枫 2006-03-31 17:30
@Ninputer
我试过不是这样的。
我这几天曾把手头上的几个C++项目,一字不改,仅将编译选项改为/clr,就编译通过了。并且运行效果完全正常。
用reflector反编译也成功的看到源码(只是源码有点不太好看)。
这几个项目有些是MFC项目,有些是API项目,都使用了模板和标准库,以及第三方的DLL。
re: C#中重用c/c++旧模块 沐枫 2006-03-31 13:21
你这项目要是没有特殊要求,其实最简单的方法是,采用C++/CLI来包装原有的dll或代码,然后就可以直接让C#引用了。
甚至可以直接用C++/CLI重编译原有代码,只增加一个或若干个接口类给.net引用。极端一点的,干脆不用C#,只用C++/CLI。
这样的做法是,简单,快捷,并且完美。甚至可以让代码同时拥有本地代码和托管代码。从而为反编译增加最大的难度。
因为不是所有的接口和struct都能很方便的封装成C#中去。
没什么讲究啦,就是看什么词容易让人理解,就是什么词好。
re: 何为仿函数 沐枫 2006-03-24 17:08
“呵呵,可以不用那么的麻烦的。 直接调用就可以了。 你可以试一试。” --@ walkspeed
--我试了,证明是一定要麻烦点,需要多加个括号。
如你自已的代码中:ObjectFunction2()(10);而不能ObjectFunction2(10)。而函数就可以。
不知道你所谓的不用那么麻烦,是如何做到的。
我不是不懂什么对象构造仿函数什么的。只是说,仿函数毕竟不是函数,不能直接调用,这一点和函数是有差别的。
re: 何为仿函数 沐枫 2006-03-24 11:06
d:\test\ttttt\ttttt\ttttt.cpp(25) : error C2440: '<function-style-cast>' : cannot convert from 'int' to 'f'
No constructor could take the source type, or constructor overload resolution was ambiguous
-------------------Source-------------
#include <iostream>
using namespace std;
class f{
public:
void operator()(int x) {
cout << x << endl;
}
};
int _tmain(int argc, _TCHAR* argv[]) {
f(10);//Error 2440
f()(10);//OK
system("Pause");
return 0;
}
re: 何为仿函数 沐枫 2006-03-24 09:03
仿函数和函数毕竟还是不同的。
比如上面的ObjectFunction2,你在调用时应该是:
ObjectFunction2()(10);
这和函数
func(10);
区别还是挺大的。
那vc6的 atlstring 有没有?我没装vc6不好意思。
re: 如何实现不可继承的类 沐枫 2006-03-22 16:14
@sunny_98
谢谢指出。我在vc2005下试,成功报错。改天我在vc7.1下再试试。
……这两个问题总得是刚从C转到C++的人容易犯的。
由于习惯了C的思维,而又不认真查阅文档,想当然耳,所犯的错误。
特别是第2个问题,不至于要这么用吧,为什么要绕几个弯呢?
CString str( "123 45" );
CString resToken;
int curPos= 0;
while (curPos != -1)
{
resToken= str.Tokenize(" ", curPos);
cout << (LPCTSTR)resToken << endl;
};
用Tokenize,不会改变源字串。
re: 模板套模板~~ 沐枫 2006-03-22 09:08
typedef一下就不糊涂了。
错误不少:
1. *p-- = *q--; // 严重错误
Fix: *q-- = *p--;
此处是要把插入点之后的字串搬到末尾。末尾的指针是q。
2. s+i-1 // 计算错误
Fix: s+i
C/C++字串是从0开始算的,因此,不需要减一。
3. char* s = "Student"; // !!! 极其严重的错误
Fix: char s[100] = "Student";
作为目的字串,必须预留足够的空间,并且不能是const.(字串常量类型是const char*)
优化建议:
1. strlen
完全可以避免strlen的调用。strlen在这里极其浪费效率。
你可以把这个做为练习,继续优化。
2. void Insert(char *s, char *s1, int i)
原型不好,难以让人知道哪个是源哪个是目的,并且也不安全。最好改为:
void Insert(char* dst, const char* src, int pos);
一般倾向于itoa,效率不错。
而且一般不爱用string而是用字符数组来存放,因为整数转换的结果不超过10个字符,不管从哪方面来说,都合算。
re: 矩形相含问题 沐枫 2005-11-16 11:08
受教了
re: [GDI+]由彩色到黑白 沐枫 2005-11-16 11:05
能不能加上两种方法的性能比较。
一般情况下,ColorMatrix的性能比较差(如果直接改象素的程序写的好的话)。
似乎只要用到ImageAttributes,GDI+性能就大幅下降。很明显的一点就是:
带Alpha的图片显示
就是比
不带Alpha而且ColorKey的图片显示
来得快得多!
re: C++博客网站正式开通 沐枫 2005-09-07 11:30
在.NET博客注册了后,如果要发表C++的随笔, 是不是要在这里再注册一个?
另外,验证码太简单了,软件比较容易识别。
最好数字用不同大小,不同的旋转角度,再加几条干扰线,再画出来,这样就不容易识别了。