博文
[置顶] C++小题,你敢挑战吗(晕死你)?(更新中)(2006-12-27 22:14:00)
摘要:1.
class B{
protected:
virtual void f( ) { cout << "B" << endl;}
public:
void g ( ) { f( ) ; }
};
class D : public B{
protected :
void f( ) { cout << "D" << endl ; }
}
int main ()
{
D d;
d . g ( );
return 0;
}
详细解答:既然是继承,g又没有覆盖,那么g就是同一个入口地址。而在调用f的时候,涉及到this指针。这个时候,this指针是基类指针。由于绑定了虚函数表,那么就会查询到实际上是指向派生类D的。于是得出结果。
这里如果把virtual去掉,那么直接进入基类的f()函数入口。
2.
class A{
public:
A( ) { a=0;}
void set_value(int x) { a=x;}
void print(){cout<<a;}
private :
int a;
};
class B:public A{
public:
&n......
cmd程序参数输入注意(2012-11-16 17:11:00)
摘要:
对于任何语言的控制台程序,可以通过工程属性中输入,也可以直接在bat中输入(注意最后加入pause命令看到结果)。
参数直接用空格即可隔开,如11 22
但是对于两个字符串,那么要注意:"aaa" "bbb" 这样也是可以的。
而路径则要注意:如"C:\aaa\" "C:\bbb\" 转义字符\"会产生一些误解。所以要写为"C:\aaa\\" "C:\bbb\\"
......
C/C++多种方法获取文件大小(2012-10-15 15:19:00)
摘要:#include <iostream>
#include <io.h>
#include <sys\stat.h>
#include <afx.h>
#define _AFXDLL
using namespace std;
void main()
{
// 此文件在工程打开状态下为不可访问
char* filepath = "..\\test.ncb";
// 方法一
struct _stat info;
_stat(filepath, &info);
int size = info.st_size;
cout<<size<<endl;
// 方法二
FILE* file = fopen(filepath, "rb");
if (file)
{
int size = filelength(fileno(file));
cout<<size<<endl;
fclose(file);
}
// 方法三
CFile cfile;
&nbs......
C++友元friend --c++利用friend修饰符,可以让一些你设定的函数(2011-09-03 17:18:00)
摘要:
通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为public(共用的),然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它,c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作,避免把类成员全部设置成public,最大限度的保护数据成员的安全。
友元能够使得普通函数直接访问类的保护数据,避免了类成员函数的频繁调用,可以节约处理器开销,提高程序的效率,但矛盾的是,即使是最大限度的保护,同样也破坏了类的封装特性,这即是友元的缺点,在现在cpu速度越来越快的今天我们并不推荐使用它,但它作为c++一个必要的知识点,一个完整的组成部分,我们还是需要讨论一下的。
1. 在类里声明一个普通函数,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员。
下面我们来看一段代码,看看我们是如何利用友元来访问类的一切成员的。
#include <iostream>
using namespace std;
class Internet
{
public:
Internet(char *name,char *address)
{
strcpy(Internet::name,name);
&nb......
#define定义函数块的语法格式(2011-05-14 15:38:00)
摘要:很少用#define来定义函数块,一是觉得麻烦,二是觉得里面可能有歧义。一般都用inline函数。
但是最近修改别人的c程序的时候,必须修改一下他写的#define函数的实现。一改不要紧,发现报了很多编译错误。才发现自己对这个语法还不是很了解。简单示例一下:
/*宏定义中允许包含两行以上的命令的情形,此时必须在最右边加上"\"*/
/* 并且 \ 的后面要紧跟回车,不能有空格,否则会报错 */
#include "stdio.h"
#define swap(a,b)
{ \
int t;\
t=a;\
a=b;\
b=t;\
} ......
heap corruption可能的原因分析(2010-03-29 11:43:00)
摘要:
最近写了点C++的代码,其中也出现过很多奇怪的错误,heap corruption detected就是其中之一,而且这种错误很容易出现。
症状一:一般在debug中出现该错误,都有大致如下的错误信息:
heap corruption detected:
after normal block(#xxx) at 0x xxxxxxxx
crt detected that the application wrote to menory after end of heap buffer
这是典型的内存溢出错误,常在内存的delete处发生,而且一般在debug版本中可能出现,release版本中可能并不报错.
出现这个错误的原因一般都是操作new申请的内存溢出,因为在c++中,如果用new分配一段内存,操作的时候改变了该部分的大小,在delete时就会出错.比如说如下部分:
char* p=new char[5];
strcpy(p,"aaaaa");
delete[] p;
这段代码就会出错,因为申请了一个size为5的内存,但是strcpy过去了一个size为6的字符串,因此破坏了这个指针,运行debug版本的时候就会出现先前的错误,但是在release版本中,溢出一个字节的内存很有可能是没有错误的,然后潜在的隐患是肯定存在的,因此,我们在debug遇到这样的错误时候一定要仔细检查对new出的指针的操作.
下面这个代码也同样会出......
关于文件读写的一些说明(2010-01-13 11:59:00)
摘要:经典问题:使用a+b模式,能读能写,但是发现不能覆盖原有记录内容。
原因分析:凡是使用了a之后,每次写数据都会在文件末尾写,而不管你把文件指针移动到哪里。用w的话,虽说不会产生总在末尾写的情况了,但每次打开文件,都会把文件清空。应该用"r+b",这样不会清空文件,也不会总在末尾写。只不过有一点要注意,由于写入和读出都使用同一个缓冲,为了防止意外发生,在写和读之间最好先刷新一下缓冲:用fflush()、fseek()或者rewind()等函数都可以,这些函数调用时都会刷新缓冲区。唯一的缺点是要首先创建这个文件。
经典问题:写入文件的代码为fprintf(fp,"%d,%d",a,b); 读出文件的代码为fscanf(fp,"%d",&a); fscanf(fp,"%d",&b); 中间的逗号哪儿去了?
原因分析:无
经典问题:读出字符串到CString,按照一般的写法 --- CString str;fscanf(fp,“%s”,&str)
不光str会出现问题,并且会影响到后面文件的关闭,出现一些奇怪的错误,切忌切忌。应该写成fscanf(fp,“%s”,str) , 但是fscanf碰到空格就会停止,有点不好; 或者使用
CString szContent;
int nFileLength = file.GetLength();
file.Read(szContent.GetBuffer(nFileLength),nFileLength);
szContent.ReleaseBuffer();
经典问题:读出字符串到string,用fgets先读出char*的buf,然后赋值,发现有换行符。通过下面这样的写法去掉换行符。
while(......
QueryPerformanceCounter/QueryPerformance(2008-07-14 14:42:00)
摘要:
QueryPerformanceCounter()这个函数返回高精确度性能计数器的值,它可以以微妙为单位计
时.但是QueryPerformanceCounter()确切的精确计时的最小单位是与系统有关的,所以,必须
要查询系统以得到QueryPerformanceCounter()返回的嘀哒声的频率.
QueryPerformanceFrequency()提供了这个频率值,返回每秒嘀哒声的个数.
计算确切的时间是从第一次调用QueryPerformanceCounter()开始的假设得到的LARGE_INTEGER 为nStartCounter,过一段时间后再次调用该函数结束的,设得到nStopCounter.两者之差除以QueryPerformanceFrequency()的频率就是开始到结束之间的秒数.由于计时函数本身要耗费很少的时间,要减去一个很少的时间开销.但一般都把这个开销忽略.
公式如下:
nStopCounter-nStartCounter
ElapsedTime=------------------------------------ - overhead
frequency
double time=(nStopCounter.QuadPart-nStartCounter.QuadPart)/frequency.QuadPart
假设要测试某个算法的消耗时间,设函数名是function()
&......
C++头文件重复包含 (2007-05-16 13:08:00)
摘要:A类中包含了B类的对象,B类中又包含了A类对象,就这么简单的一个问题,我都搞不定,后来查了资料才搞定。
这实际上是INCLUDE重复包含的问题,造成编译不通过。不过还是找到了资料
供大家参考!
http://www.yesky.com/127/1736627_3.shtml
(很多Visual C++书籍对这些问题避而不谈,但实际上这是一个重要的问题。如果不能理解上述代码,我们很可能为无法通过编译而大伤脑筋。这些问题的出现是基于这样的一些事实:在我们用标准C/C++设计程序时,有一个原则即两个代码文件不能相互包含,而且多次包含还会造成重复定义的错误。为了解决这个难题,Visual C++使用#pragma once来通知编译器在生成时只包含(打开)一次,也就是说,在第一次#i nclude之后,编译器重新生成时不会再对这些包含文件进行包含(打开)和读取,因此我们看到在用向导创建的所有类的头文件中有#pragma once语句就不会觉得奇怪了。然而正是由于这个语句而造成了在第二次#i nclude后编译器无法正确识别所引用的类。因此,我们在相互包含时还需要加入类似class CViewerView这样的语句来通知编译器这个类是一个实际的调用。)......
一道C++程序员的考题让我重新审视多态(2006-11-11 22:20:00)
摘要:班上一位同学参加了软考,问我这样一道题目,结果出乎我的意料:
class SalesTicket {
public:
virtual void printTicket(){cout<<"\n这里是正文"<<endl;}
};
class Decorator:public SalesTicket{
SalesTicket *ticket;
public:
Decorator(SalesTicket *t){ticket=t;}
void printTicket(){
if(ticket!=NULL){
ticket->printTicket();}
}
};
class HeadDecorator:public Decorator{
public:
HeadDecorator(SalesTicket *t):Decorator(t){}
void printTicket(){
cout<<"\n这里是票据的抬头"<<endl;
Decorator::printTicket();
}
};
class FootDecorator:public Decorator{
public:
FootDecorator(SalesTicket *t):Decorator(t){}
void printTicket(){
Decorator::printTicket();
cout<<"\n这里是票据的脚注"<<endl;
}
};
void main(void)
{
SalesTicket t;
FootDecorator f(&t);
He......