自己不熟悉的c++知识点

来源:互联网 发布:sd卡数据恢复手机软件 编辑:程序博客网 时间:2024/05/17 00:53

1.模板

template<class type>

void function(type a )
{
}


2.三种传递类型

void function(int &a, int &b)
{
}
void function2(int a, int b)
{
}
void function3(int* a, int* b)
{
}


3.删除内存

delete [] q; //数组

delete q; //指针


4.内联函数

inline int min( int v1, int v2 ) { /* ... */ }


5数组指针

int main( int argc, char *argv[] ) { ... }


6.函数指针

int min( int*, int );
int (*pf)( int*, int ) = min;

调用
pf( ia, iaSize );
也可以用显式的指针符号写出
(*pf)( ia, iaSize );

typedef int ( *PFI2S )( const string &, const string & );


7.typedef

typedef char Line[81];
此时Line类型即代表了具有81个元素的字符数组,使用方法如下:

8.类的不同定义
class Screen { /* ... */ };
class Screen { /* ... */ } myScreen, yourScreen;

9.类中的链表
class LinkScreen {
Screen window;
LinkScreen *next;
LinkScreen *prev;
};

10.#define
#define min(x, y) x+y
cout<<min(1,2)<<endl;


#define STRING(x) #x//字符
cout<<STRING( test_string )<<endl;


#define SIGN( x )  INT_##x//连接
int SIGN(TEST)=1;
cout<<SIGN(TEST)<<endl;

11.习惯
if (0 == x)好习惯
for (i=0; i<10; i++) // 良好的风格
for(i=0;i<10;i++) // 不良的风格
for (i = 0; I < 10; i ++) // 过多的空格
int *x, y; // 此处y 不会被误解为指针
} // end of while
} // end of if

if (flag) // 表示flag 为真
if (!flag) // 表示flag 为假
其它的用法都属于不良风格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)
在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的
循环放在最外层,以减少CPU 跨切循环层的次数

我们不要将
return int(x + y); // 创建一个临时变量并返回它
写成
int temp = x + y;
return temp;

12.头文件开头处的版权和版本声明

/*
*Copyright (c) 2013,杭州游戏公司
*All rights reserved
*
*文件名称: filename.h
*摘       要:描述内容
*
*
*作       者:红星
*完成日期:2013年1月1日
*/


13.}以行为为中心的版式
class A
{
public:
void Func1(void);
void Func2(void);

private:
int i, j;
float x, y;

}


14.命名规则

类名和函数名用大写字母开头的单词组合而成
class Node;
void Draw(void);

变量和参数用小写字母开头的单词组合而成
BOOL flag;
int drawMode;

常量全用大写的字母,用下划线分割单词。
const int MAX = 100;
const int MAX_LENGTH = 100;

静态变量加前缀s_(表示static)。
例如:
void Init(…)
{
static int s_initValue; // 静态变量

}

如果不得已需要全局变量,则使全局变量加前缀g_(表示global)。
例如:
int g_howManyPeople; // 全局变量
int g_howMuchMoney; // 全局变量

类的数据成员加前缀m_(表示member),这样可以避免数据成员与
成员函数的参数同名。
例如:
void Object::SetValue(int width, int height)
{
m_width = width;
m_height = height;
}


15.类中的const

class A
{…
const int SIZE = 100; // 错误,企图在类声明中初始化const 数据成员
int array[SIZE]; // 错误,未知的SIZE
};
const 数据成员的初始化只能在类构造函数的初始化表中进行,例如
class A
{…
A(int size); // 构造函数
const int SIZE ;
};
A::A(int size) : SIZE(size) // 构造函数的初始化表
{

}
A a(100); // 对象 a 的SIZE 值为100
A b(200); // 对象 b 的SIZE 值为200

怎样才能建立在整个类中都恒定的常量呢?别指望const 数据成员了,应该用类中
的枚举常量来实现。例如
class A
{…
enum { SIZE1 = 100, SIZE2 = 200}; // 枚举常量
int array1[SIZE1];
int array2[SIZE2];
};


16.内存分配方式有三种

(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的
整个运行期间都存在。例如全局变量,static 变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函
数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集
中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多
少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期
由我们决定,使用非常灵活,但问题也最多。


17.malloc和new

void UseMallocFree(void)
{
Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存
a->Initialize(); // 初始化
//…
a->Destroy(); // 清除工作
free(a); // 释放内存
}

void UseNewDelete(void)
{
Obj *a = new Obj; // 申请动态内存并且初始化
//…
delete a; // 清除并且释放内存
}

18.注意

int *p2 = new int[length];
Obj *b = new Obj(1); // 初值为1
::Print(…); // 表示Print 是全局函数而非成员函数

char *p = "world"; // 注意p 指向常量字符串

正确的示例如下:
void Foo(int x, int y=0, int z=0);
错误的示例如下:
void Foo(int x=0, int y, int z=0);

class Derived : public Base
{
public:
void f(int y){Base::f(y); cout<<2;}
};

19.内联函数写法

void Foo(int x, int y);
inline void Foo(int x, int y) // inline 与函数定义体放在一起
{

}


20.拷贝构造函数和赋值函数

// 拷贝构造函数
String::String(const String &other)
{
// 允许操作other 的私有成员m_data
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data, other.m_data);
}


// 赋值函数
String & String::operate =(const String &other)
{
// (1) 检查自赋值
if(this == &other)
return *this;
// (2) 释放原有的内存资源
delete [] m_data;
// (3)分配新的内存资源,并复制内容
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data, other.m_data);
// (4)返回本对象的引用
return *this;
}


21.析构函数

基类的构造函数、析构函数、赋值函数都不能被派生类继承。
基类与派生类的析构函数应该为虚(即加virtual 关键字)。例如
#include <iostream.h>
class Base
{
public:
virtual ~Base() { cout<< "~Base" << endl ; }
};
class Derived : public Base
{
public:
virtual ~Derived() { cout<< "~Derived" << endl ; }
};
void main(void)
{
Base * pB = new Derived; // upcast
delete pB;
}
输出结果为:
~Derived
~Base
如果析构函数不为虚,那么输出结果为
~Base

22.函数中的const

例如不要将函数void Func1(int x) 写成void Func1(const int x)。同理不要将
函数void Func2(A a) 写成void Func2(const A a)。

应该为void Func(const A &a)。

是否应将void Func(int x) 改写为void Func(const int &x),以便提
高效率?完全没有必要,因为内部数据类型的参数不存在构造、析构的过程

例如函数
const char * GetString(void);
如下语句将出现编译错误:
char *str = GetString();
正确的用法是
const char *str = GetString();

如果返回值不是内部数据类型,将函数A GetA(void) 改写为const A & GetA(void)
的确能提高效率

int GetCount(void) const; // const 成员函数
int Stack::GetCount(void) const
{
++ m_num; // 编译错误,企图修改数据成员m_num
Pop(); // 编译错误,企图调用非const 函数
return m_num;
}

23.函数指针

typedef void(*Fun)(void);//函数指针
Fun pf=&function;
(*pf)();

void (*pf)(void)=&function;
(*pf)();

typedef void(A::*PMA)(char *, const char *);
PMA pmf= &A::strcat; // pmf是PMF类型(类A成员指针)的变量

void(Class::*pf)()=&(Class::function);//成员函数
(A.*pf)();



void touppercase(char *, const char*) const;
//解决的方法是声明一个const类型的成员指针:
void (A::pcmf)(char *, const char *) const; 
pcmf=&A::touppercase; // 现在可以了



23.指针const

const int* a = &b; [1]
int const *a = &b; [2]
,[1]和[2]的情况相同,都是指针所指向的内容为常量
如不能*a = 3


int* const a = &b; [3]
这种情况下不能对指针本身进行更改操作,如a++是错误的


const int* const a = &b; [4]
[4]为指针本身和指向的内容均为常量。


24.函数参数地址

simple_va_fun(10,20,30,40);
void simple_va_fun(int i, ...) 

cout<<i<<endl<<*(&i+1)<<endl<<*(&i+2)<<endl<<*(&i+3);
}


25.异常处理

try{2         cout<<"This an easy exception example."<<endl;3         throw 1;4     }6     catch(int i)
   {7         cout<<"Catched the exception: i = "<<i<<endl;8     }
   catch(...)
   {5         cout<<"Catched the exception."<<endl;
   }


原创粉丝点击