一、函数指针
func.h: #ifndef FUNC_H_ #define FUNC_H_ #include <string> #include <iostream> int compare(const std::string& s1, const std::string& s2); // 普通函数 typedef int (*COMP)(const std::string& s1, const std::string& s2); void myfun(std::string *s1, std::string *s2, COMP comp=compare); // 参数中含有函数指针,可以有默认值 #endif
func.cpp: #include "func.h" #include <string> #include <iostream> int compare(const std::string& s1, const std::string& s2) { return s1.compare(s2); } void myfun(std::string *s1, std::string *s2, COMP comp) { std::cout << "myfun:comp('" << *s1 << "','" << *s2 << "'): " << comp(*s1, *s2) << std::endl; }
main.cpp: #include <iostream> #include <vector> #include "func.h" using namespace std; int main(int argc, char* argv[]) { cout << "Hello World!!!" << endl; cout << "compare('aaa','bbb'): " << compare("aaa", "bbb") << endl; // 普通调用 int (*fp)(const string&, const string&); fp = compare; cout << "function pointer: " << fp("aaa", "bbb") << endl; // 通过函数指针调用 fp = &compare; // 和上面等价 cout << "function pointer: " << fp("aaa", "bbb") << endl; string s1("aaa"); string s2("bbb"); myfun(&s1, &s2, fp); // 把函数指针作为参数传到一个函数中去 return 0; }
运行结果:
Hello World!!! compare('aaa','bbb'): -1 function pointer: -1 function pointer: -1 myfun:comp('aaa','bbb'): -1
二、static关键字
1. 面向过程 * static全局变量:只能在本文件中访问。和普通全局变量的区别就是作用域被限制在一个文件中 * static局部变量:函数退出时仍保持其值不释放。普通的局部变量在函数退出时会被释放 * static函数:只能在本文件中访问。普通函数通过extern的方式(一般定义在头文件中)可被用于其它文件中。 2. 面向过程 * static属性或方法:属于类而非某个对象。不能调用非static成员,当非static成员可以调用它。这个和JAVA没有区别
三、namespace
作用就是在全局命名空间(::)中继续划分子空间。子空间的定义会覆盖父空间的定义。和JS中的域差不多。
1.定义 namespace MySpace { // 各种定义 namespace InnerSpace1{ // 可以嵌套 // 各种定义,会覆盖外层同名的定义 } } 2. 使用 * MySpace::xxx // 直接使用域前缀的方式去访问该命名空间下的成员 * using MS=MySpace; // 别名 MS::xxx // 使用域前缀的方式访问。类似于JAVA的全类名java.util.List * using MySpace::xxx; // 使xxx可见。类似于JAVA的import java.util.List; xxx.fun(); // 类似于JAVA的ist.add(); * using MySpace; // 使该空间下的所有成员可见。类似于JAVA的import java.util.*; xxx.fun();
四、函数重载
* 函数名相同,参数的个数、类型、顺序不同 * 不考虑返回类型,不考虑参数名称 * 不考虑形参的const,volatile修饰符 (指针和引用类型的除外) * 只考虑typedef所代表的底层类型 * 不考虑形参是否缺省
五、函数的几种返回类型
class Test { public : Test(){val=0;} Test(int v) { val = v; } ~Test(){val=-1;} inline int get(){return val;} inline void set(int v){val = v;} private : int val; }; Test getTest1() { // Test t(100); // return t; // 会调用拷贝构造,然后析构t // Test t(100); // Test &rt = t; // return rt; // 同上 Test *t = new Test(100); return *t; // 会照成内存泄露。函数结束后,t变量消失,但其所指向的对象没有释放(delete t) } Test& getTest2() { // Test t(100); // return t; // 函数结束后t被析构,返回值指向一个无效的内存区域 // Test t(100); // Test& rt = t; // return rt; // 同上 Test *t = new Test(100); return *t; // 函数结束后t消失,而返回的引用指向了被new出来的内存。但是因为返回的不是一个指针,所以无法通过delete去释放这块内存,造成内存泄露 } Test* getTest3() { // Test t(100); // return &t; // 函数结束后t被析构,返回的指针变成野指针 // Test t(100); // Test &rt = t; // return &rt; // 同上 Test *t = new Test(100); return t; // 较好 } void f () { Test t = getTest1(); cout << t.get() << endl; // Test t = getTest2(); // cout << t.get() << endl; // Test *pt = getTest3(); // cout << pt->get() << endl; } int main(int argc, char* argv[]) { f(); return 0; }
六、引用基本知识
引用的主要作用是: 1.函数形参 2. 函数返回值 3. const引用
int i = 100; int &ri = i; // 引用的声明 cout << "ri=" << ri << endl; int &rri = ri; // 这里的ri就是i,实际上相当于: int &rri = i;为i分配了第二个别名rri cout << "rri=" << rri << endl; int j = ri; // 相当于i=j cout << "j=" << j << endl; int k = 200; const int &rk = k; // 常引用 //rk = 300; // 不能通过常引用去修改k k = 300; // 但是我们可以直接修改k cout << "rk=" << rk << endl; // 300 int &nrk = k; // k的第二个别名(注意是非const引用) nrk = 400; // 通过nrk可以修改k,此时的rk跟着一起变 cout << "rk=" << rk << endl;