C++
来源:互联网 发布:mac自动刷新功能 编辑:程序博客网 时间:2024/06/06 16:34
//函数模板template <typename T>int compare(T &v1, T&v2) {}
引用 http://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html
0.基本特性
int a;int &ra = a; // 引用必须初始化,它只是某个变量的别名(没有自己的存储空间)ra = 1; // 对引用的修改就是对原变量的修改
1.引用作为参数
目的:避免参数值拷贝,提高效率。
2.引用作为返回值
目的:避免拷贝;返回同一个变量,有利于做链式操作。
场景:返回值做为左值时必须用引用; count << "hello" << end; // 流操作符 赋值操作
注意:
1.局部变量不能做为引用返回(变量的生命周期已经结束)
2.不要返回函数内的new分配的内存的引用,申请的内存不好释放。
int &func(const String &rb); // 引用做为形参,函数体中对形参的修改就是对外部调用的实参的修改。没有拷贝一份实参,提高了效率
操作符重载 http://www.cnblogs.com/xiangxiaodong/archive/2012/02/12/2348144.html
class Person{ private: int age; public: Person(int a) {age = a;} bool <span style="color:#ff0000;"><strong>operater==</strong></span> (const Person &rb); // 定义}// 做为类的成员函数来实现bool Person::operator== const Person &rb{ if (<span style="color:#ff0000;">this</span>.age == rb.age) return true; return false;}// 非成员函数的实现bool operator== (Person &<span style="color:#ff0000;">ra</span>, Person &rb){ if (<span style="color:#ff0000;">ra</span>.age == rb.age) return true; return false;}// 使用Person a(10);Person b(20);if (a == b) ; // a对象调用比较运算,b做为参数
virtual虚函数
0.目的:
子类覆盖父类的方法。
所以:关键字在对象环境中才有意义
虚函数是运行时确定的。
因此:静态成员函数(针对一个类非对象),构造函数(对象还没有生成),内联函数(编译期间确定) 都不能声明为virtual的。
1.实现:
父类中被覆盖的方法前面加此关键字。子类该方法默认带这个关键字。
表面子类继承了父类的函数,但要重写override它(函数定义一模一样,允许返回值不同)。
2.注意:
基类的指针调用函数,有virtual的调用子类的函数,否则调用基类的函数。
用子类的指针调用,一律调用子类的函数。
//根据不同子类构造的基类指针,调用相应子类的方法,称为多态。虚函数通过指针或者引用来实现多态。
virtual void foo()=0; // 纯虚函数,拥有它的类为抽象类,提供了多态的接口。
#include <iostream.h>class Base{public:virtual void f(float x){ cout << "Base::f(float) " << x << endl; }void g(float x){ cout << "Base::g(float) " << x << endl; }void h(float x){ cout << "Base::h(float) " << x << endl; }}; class Derived : public Base{public:virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }void g(int x){ cout << "Derived::g(int) " << x << endl; }void h(float x){ cout << "Derived::h(float) " << x << endl; }}; void main(void){Derived d;Base *pb = &d;Derived *pd = &d;// Good : behavior depends solely on type of the objectpb->f(3.14f); // Derived::f(float) 3.14pd->f(3.14f); // Derived::f(float) 3.14// Bad : behavior depends on type of the pointerpb->g(3.14f); // Base::g(float) 3.14pd->g(3.14f); // Derived::g(int) 3 (surprise!)// Bad : behavior depends on type of the pointerpb->h(3.14f); // Base::h(float) 3.14 (surprise!)pd->h(3.14f); // Derived::h(float) 3.14}
函数的重载
0.目的:
根据参数的区别来调用同一类函数。
1.实现:
在一个类中实现几个函数名相同,参数不同的函数。
指针
1. 利用形参修改指针的值
void GetMemory2(char **p, int num){ *p = (char *)malloc(sizeof(char) * num);}
void Test(void){ char *str=NULL; GetMemory(&str, 100); strcpy(str,"hello world"); printf(str);}
类
C++空类默认的成员函数
class Empty{public: Empty(); // 缺省构造函数 Empty( const Empty& ); // 拷贝构造函数 ~Empty(); // 析构函数 Empty& operator=( const Empty& ); // 赋值运算符 Empty* operator&(); // 取址运算符 const Empty* operator&() const; // 取址运算符 const};
String类的实现
class String{ public: String(const char *str = NULL); // 普通构造函数 String(const String &other); // 拷贝构造函数 ~ String(void); // 析构函数 String & operate =(const String &other); // 赋值函数 private: char *m_data; // 用于保存字符串 };//普通构造函数String::String(const char *str) { if(str==NULL) { m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志'\0'的空 //加分点:对m_data加NULL 判断 *m_data = '\0'; } else { int length = strlen(str); m_data = new char[length+1]; // 若能加 NULL 判断则更好 strcpy(m_data, str); }}// String的析构函数String::~String(void) { delete [] m_data; // 或delete m_data;}//拷贝构造函数String::String(const String &other) // 得分点:输入参数为const型{ int length = strlen(other.m_data); m_data = new char[length+1]; //加分点:对m_data加NULL 判断 strcpy(m_data, other.m_data); }//赋值函数String & String::operate =(const String &other) // 得分点:输入参数为const型{ if(this == &other) //得分点:检查自赋值 return *this; delete [] m_data; //得分点:释放原有的内存资源 int length = strlen( other.m_data ); m_data = new char[length+1]; //加分点:对m_data加NULL 判断 strcpy( m_data, other.m_data ); return *this; //得分点:返回本对象的引用}
const
1. 修饰为常量
A const int* a = &b; //指针指向的是常量,但指针可变。 B const* int a = &b; //指针是常量,指向的值可变C const int* const a = &b; //a和*a都是const,常量和指针的值都不能改变D int const* const a = &b; //a和*a都是const,常量和指针的值都不能改变
extern
sizeof()的用法
sizeof操作符的结果类型是size_t,它在头文件 中typedef为unsigned int类型。
1. sizeof(p) = 4; // 指针的大小为4字节,数组做参数时沦为指针类型,其大小为4.2. char str[] = "abcd"; // sizeof(str) = 5, 得到静态数组的大小,包括字串结束符;区别:strlen(str)=4;求字串的大小,不包括结束符。
对齐
目的:提高CPU存储变量的速度
实现:
1.系统默认对齐 == 每个变量的偏倚地址是此变量大小的倍数 && 总空间大小是最大变量大小的倍数
struct MyStruct { char dda; //偏移量为0,满足对齐方式,dda占用1个字节; double dda1;//下一个可用的地址的偏移量为1,不是sizeof(double)=8 的倍数,VC需要补足7个字节满足对齐方式,dda1存放在偏移量为8的地址上,它占用8个字节。 int type;//下一个可用的地址的偏移量为16,是sizeof(int)=4的倍数,满足int的对齐方式,所以不需要VC自动填充,type存放在偏移量为16的地址上,它占用4个字节 };//所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,不是结构 //的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以需要填充4个字节。所以该结构总的大小为:sizeof(MyStruc)为1+7+8+4+4=24。其中总的有7+4=11个字节是VC自动填充的,没有放任何有意义的东西。
2.自定义对齐
n字节对齐 == 变量存放的起始地址的偏移量为min(n, 默认值)
#pragma pack(push) //保存对齐状态 #pragma pack(4) //设定为4字节对齐 struct test { char m1; double m4; int m3; }; #pragma pack(pop)//恢复对齐状态 以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为 m4分配空间,这时其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于n),m4占用8个字节。接着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。
1. 数组的大小要求为编译期间常量
unsigned int temp = 3;unsigned int const size = temp;char str[ size ]; // 编译错误,运行时才知道数组的大小。如果unsigned int const size = 3; char str[size]; 这样定义OK。
int id[sizeof(unsigned long)]; // 这个对。sizeof是编译时运算符,编译时就确定了可以看成和机器有关的常量。
BOOL型变量:if(!var)int型变量: if(var==0)float型变量:const float EPSINON = 0.00001; if ((x >= - EPSINON) && (x <= EPSINON)指针变量: if(var==NULL)
模板
1.函数模板
template <typename T>int compare(T &v1, T&v2) {...}2.类模板 eg. vector, map
template <class Type>class myQueue:Queue<Type>{public: void push(const Type &); ...}