内存管理函数:memcpy() memmove() memchr() memcmp() memset() strncpy()
void* memcpy(void* destination, const void* source, size_t num);
****The function does not check for any terminating null character in source - it always copies exactly num bytes.

/* memcpy example */
#include <stdio.h>
#include <string.h>

int main()
{
 char str1[] = "sample string";
 char str2[40];
 char str3[40];
 memcpy(str2, str1, strlen(str1) + 1);
 memcpy(str3, "copy successful", 16);
 printf("str1: %s\nstr2: %s\nstr3: %s\n", str1, str2, str3);
 return 0;
}

/* memmove() funtion */
Moves one buffer to another. Secure version are available, memmove_s(), wmemmove_s()
void* memmove(
 void* dest,
 const void* str,
 size_t count);
/* memchr() function */
Finds characters in a buffer.
void* memchr(
 const void* buf,
 int c,
 size_t count 
); // C only
void* memchr(
 void* buf,
 int c,
 size_t count
); // C++ only

/* memcmp() function */
Compare characters in two buffers.
int memcmp(
 const void* buf1,
 const void* buf2,
 size_t count
);

/* memset */
Sets buffers to a specified character.
void* memset(
 void* dest,
 int c,
 size_t
);

/* strncpy() function */
Copy characters of one string to another.
char* strncpy(
 char* strDest,
 const char* strSource,
 size_t count
);

 
如果一个变量你需要几种可能存在的值,那么就可以被定义成为枚举类型。之所以叫枚举就是说将变量或者叫对象可能存在的情况也可以说是可能的值一一例举出来。 

  举个例子来说明一吧,为了让大家更明白一点,比如一个铅笔盒中有一支笔,但在没有打开之前你并不知道它是什么笔,可能是铅笔也可能是钢笔,这里有两种可能,那么你就可以定义一个枚举类型来表示它!

enum box{pencil,pen};//这里你就定义了一个枚举类型的变量叫box,这个枚举变量内含有两个元素也称枚举元素在这里是pencil和pen,分别表示铅笔和钢笔。

  这里要说一下,如果你想定义两个具有同样特性枚举类型的变量那么你可以用如下的两种方式进行定义!

enum box{pencil,pen};  
  
enum box box2;//或者简写成box box2;

  再有一种就是在声明的时候同时定义。

enum {pencil,pen}box,box2; //在声明的同时进行定义!

  枚举变量中的枚举元素系统是按照常量来处理的,故叫枚举常量,他们是不能进行普通的算术赋值的,(pencil=1;)这样的写发是错误的,但是你可以在声明的时候进行赋值操作!

enum box{pencil=1,pen=2};

  但是这里要特别注意的一点是,如果你不进行元素赋值操作那么元素将会被系统自动从0开始自动递增的进行赋值操作,说到自动赋值,如果你只定义了第一个那么系统将对下一个元素进行前一个元素的值加1操作,例如


  前面说了那么多,下面给出一个完整的例子大家可以通过以下的代码的学习进行更完整的学习!

#include <iostream>  
using namespace std;  
  
void main(void)  
{  
    enum egg {a,b,c};  
    enum egg test; //在这里你可以简写成egg test;  
  
    test = c; //对枚举变量test进行赋予元素操作,这里之所以叫赋元素操作不叫赋值操作就是为了让大家明白枚举变量是不能直接赋予算数值的,例如(test=1;)这样的操作都是不被编译器所接受的,正确的方式是先进行强制类型转换例如(test = (enum egg) 0;)!  
  
    if (test==c)  
    {  
        cout <<"枚举变量判断:test枚举对应的枚举元素是c" << endl;  
    }  
  
    if (test==2)  
    {  
        cout <<"枚举变量判断:test枚举元素的值是2" << endl;  
    }  
  
    cout << a << "|" << b << "|" << test <<endl;  
  
    test = (enum egg) 0; //强制类型转换  
    cout << "枚举变量test值改变为:" << test <<endl;  
    cin.get();  
}

  看到这里要最后说一个问题,就是枚举变量中的枚举元素(或者叫枚举常量)在特殊情况下是会被自动提升为算术类型的!

#include <iostream>  
using namespace std;  
  
void main(void)  
{  
    enum test {a,b};  
    int c=1+b; //自动提升为算术类型  
    cout << c <<endl;  
    cin.get();  
}

 
关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的《C++ 的设计和演化》。最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_cast, dynamic_cast。标准C++中有四个类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。下面对它们一一进行介绍。static_cast

用法:static_cast < type-id > ( expression_r_r )

该运算符把expression_r_r转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
把空指针转换成目标类型的空指针。
把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression_r_r的const、volitale、或者__unaligned属性。

dynamic_cast

用法:dynamic_cast < type-id > ( expression_r_r )

该运算符把expression_r_r转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression_r_r也必须是一个指针,如果type-id是一个引用,那么expression_r_r也必须是一个引用。

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。

在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
class B{

public:

int m_iNum;

virtual void foo();

};

class D:public B{

public:

char *m_szName[100];

};

 

void func(B *pb){

D *pd1 = static_cast<D *>(pb);

D *pd2 = dynamic_cast<D *>(pb);

}

在上面的代码段中,如果pb指向一个D类型的对象,pd1和pd2是一样的,并且对这两个指针执行D类型的任何操作都是安全的;但是,如果pb指向的是一个 B类型的对象,那么pd1将是一个指向该对象的指针,对它进行D类型的操作将是不安全的(如访问m_szName),而pd2将是一个空指针。另外要注意:B要有虚函数,否则会编译出错;static_cast则没有这个限制。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见<Inside c++ object model>)中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。

另外,dynamic_cast还支持交叉转换(cross cast)。如下代码所示。
class A{

public:

int m_iNum;

virtual void f(){}

};

 

class B:public A{

};

 

class D:public A{

};

 

void foo(){

B *pb = new B;

pb->m_iNum = 100;

D *pd1 = static_cast<D *>(pb); //copile error

D *pd2 = dynamic_cast<D *>(pb); //pd2 is NULL

delete pb;

}

在函数foo中,使用static_cast进行转换是不被允许的,将在编译时出错;而使用 dynamic_cast的转换则是允许的,结果是空指针。

reinpreter_cast

用法:reinpreter_cast<type-id> (expression_r_r)

type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。

该运算符的用法比较多。

const_cast

用法:const_cast<type_id> (expression_r_r)

该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression_r_r的类型是一样的。

常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

Voiatile和const类试。举如下一例:
class B{

public:

int m_iNum;

}

void foo(){

const B b1;

b1.m_iNum = 100; //comile error

B b2 = const_cast<B>(b1);

b2. m_iNum = 200; //fine
}

上面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;使用const_cast把它转换成一个常量对象,就可以对它的数据成员任意改变。注意:b1和b2是两个不同的对象。

最容易理解的解释:

   dynamic_cast:   通常在基类和派生类之间转换时使用;
   const_cast:   主要针对const和volatile的转换.   
   static_cast:   一般的转换,如果你不知道该用哪个,就用这个。   
   reinterpret_cast:   用于进行没有任何关联之间的转换,比如一个字符指针转换为一个整形数。

 
private 函数在类外面是不能被调用的,那么它有什么作用呢?(头脑风暴)
1.  通过函数的形式构建代码块,供各种函数成员调用;
2.  可以修改类的private成员变量;
3.  为什么不能公开呢?公开又会带来什么问题呢?
4.  类的成员变量中,有私有成员变量,不能在类的外面被直接调用或改变, 这些私有成员变量的改变通过成员函数实现,如果修改了私有成员变量的成员函数被调用,会不会暴露私有成员呢?貌似不会...
5. 那这样的话,私有函数就是不需要被外部调用(或者可以说与用户无关)的类的私有代码片段;
6. 那私有构造函数呢?通过工厂模式创建对象,而不能用new的方式自己调用构造函数创建对象;但是为什么呢?
7. 私有构造函数后,可以实现单例模式,保证某个单例类的实例对象最多一个;可是为什么引入工程模式创建对象呢?
8. 节选《http://hi.baidu.com/periskyl/blog/item/e1d8b8ae130f59054a36d679.html
为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量
9. 就这些吧...呵呵

姚鑫

2011/8/11

 
http://blog.3snews.net/?uid-6188-action-spacelist-type-blog-itemtypeid-1062


Recently, I am working at GIS-based app. I decide to use KML files as data scripts. The web link above is good blog about libkml library. Note it here.

Jackson Yao
2011/7/18

 
in c language, char should end with '\0', it tells compiler the char[] has ended. 
see example code:
char tmpbuf[128], ampm[]="000";
char time2[13] ;
printf("\n%s\n", time2);

the output result is unexpected, ending with 000, or *************000, * represent for unknown character.
the solution is to add a initialization code to time2 array :
char time2[13] = {0};
this tells us that  when U create a array, U 'd better initialize the array with '\0' , as to 0;
 
Today, I want to convert a date&time value to a string or char*, for example "110608153532", representing for 2011/06/08 15:35:32 . Microsoft MSDN provides various functions for us to use and get system time value in different kinds. see example codes. see it : http://msdn.microsoft.com/en-us/library/1f4c8f33(v=VS.100). I can add a handler to gain what I want to .
2011/6/8 yao
 
from: msdn.microsoft.comThis keyword is a declaration specifier that can only be applied to in-class constructor declarations. An explicit constructor cannot take part in implicit conversions. It can only be used to explicitly construct an object.

// spec1_explicit.cpp // compile with: /EHsc #include <stdio.h>  class C { public: int i; explicit C(const C&) // an explicit copy constructor { printf_s("\nin the copy constructor"); }  explicit C(int i ) // an explicit constructor { printf_s("\nin the constructor"); }  C() { i = 0; } }; class C2 { public: int i; explicit C2(int i ) // an explicit constructor { } }; C f(C c) { // C2558 c.i = 2; return c; // first call to copy constructor } void f2(C2) { }  void g(int i) { f2(i); // C2558 // try the following line instead // f2(C2(i)); } int main() {  C c, d;  d = f(c); // c is copied }

The following program will fail to compile because of the explicit keyword. To resolve the error, remove the explicit keywords and adjust the code in g.
 

// Operator learning
// C++ programming language
// P233
namespace user
{
namespace math
{

struct complex
{
douple re, im;
// 
complex(double r, double i) : re(r), im(i){};
complex &operator+(complex &_cpx);
complex &operator*(complex &_cpx);
}

}

}

complex &user::math::complex::operator+(complex &_cpx){
complex cpx;
cpx.re = this.re + _cpx.re;
cpx.im = this.im + _cpx.im;
return cpx; 
}

complex &user::math::complex::operatro*(complex &_cpx){
complex cpx;
cpx.re = this.re * _cpx.re - this.im * _cpx.im;
cpx.im = this.re * _cpx.im + this.im * _cpx.re;
return cpx;
}

// any other code ?
// find something from Internet
// sample of Operatro overloading
#include <string>
class PlMessageHeader
{
std::string m_ThreadSender;
std::string m_ThreadReceiver;

// return true if the messages are equal, false otherwise
inline bool operator == (const PlMessageHeader &b) const
{
return ( (b.m_ThreadSender == m_ThreadSender) &&
(b.ThreadReceiver == m_ThreadReceiver) );
}

// return true if the message is for name
inline bool isFor (const std::string &name) const
{
return (m_ThreadReceiver == name);
}
// return true if the message is for name
inline bool isFor (const char *name) const
{
// since name type is std::string, 
// it becomes unsafe if name == NULL. 
return (m_ThreadReveiver == name);
}
}

// Operators as member functions
// binary operator as member function
Vector2D Vector2D::operator+(const Vector2D &right) const {...}

// binary operator as non-member function
Vector2D operator+(const Vector2D &left, const Vector2D &right) 
{
//...
Vector2D result;
result.set_x(left.x() + right.x());
result.set_y(left.y() + right.y());

return result;
}

// binary operator as member function with dual arguments
friend Vector2D operator+(const Vector2D &left, const Vector2D &right) {...}

// unary operator as member function
Vector2D Vector2D::operator-() const {...}

// unary operator as mon-member function
Vector2D operator-(const Vector2D &vec){...}

// An example using a 2D vector
friend ostream& operator<<(ostream& out, const Vector2D& vec) // output
{
out << "(" <<vec.x() << ", " << vec.y() << ")";
return out;
}

friend istream& operator>>(istream& in, Vector2D& vec)// input
{
double x, y;
in >> x >>y;
vec.set_x(x);
vec.set_y(y);
return in;
}
 
recv function declaration:
 int recv(SOCKET s, char FAR* buf, int len, int flags);
s[in] : the descriptor that identifies a connected socket.
buf[out] : a pointer to the buffer to receive the incoming data.
len[in] : the length , in bytes, of the buffer pointed to by the buf parameter.
flags[in] : a set of flags that influences the behavior of this function.  

Following is sth about recv() function executing proess in SOCKET:
1. process A calls recv(), recv() function have to wait for DATA IN SEND BUF(发送缓冲)  being transmited by protocol, if there are some errors in transmition about DATA IN SEND BUF, the function return SOCKET_ERROR. 
2. after transmition about DISB,   recv() checks RECV BUF(RB); if socket s[in]'s RB is empty or is receiving data, recv() has to block for a while.
3. after protocol receiving data, recv() copies data in RB to buf[in] (WARNING: data received by protocol may be larger than len[in], length of buf[in], if so, process has to call recv() for several times to copy data in RECV BUF. A IMPORT POINT is that : in fact recv() is just copying data from RB to some buffer, buf[in], and protocol, for example TCP/I&UDP, is the real receiver of data from netwrok part.  )
4. the returning value of recv() is bytes number copied by the function recv(), if an error occurs in "recving", it returns SOCKET_ERROR, and it returns 0 while network is cutted down.  
from: www.wenku.baidu.com
J.Yao 2011-5-14