一、构造函数
class NoName { public: NoName(); explicit NoName(const char *); NoName(const char *, int); NoName(const char *, int, double); NoName(const NoName&); virtual ~NoName(); protected: char *pstr; int ival; double dval; private : void initNoName(const char *ps); }; void NoName::initNoName(const char *ps) { if (ps) { pstr = new char[strlen(ps)+1]; strcpy(pstr, ps); } else { pstr = new char[1]; *pstr = '\0'; } } NoName::NoName() { pstr = new char[1]; *pstr = '\0'; ival = 0; dval = 0; } NoName::NoName(const char *ps) { initNoName(ps); ival = 0; dval = 0; } NoName::NoName(const char *ps, int i) { initNoName(ps); ival = i; dval = 0; } NoName::NoName(const char *ps, int i, double d) { initNoName(ps); ival = i; dval = d; } NoName::NoName(const NoName &rhs) { initNoName(rhs.pstr); ival = rhs.ival; dval = rhs.dval; } NoName::~NoName() { delete pstr; pstr = 0; }
使用带缺省值的构造函数:
class NoName { public: NoName(const char *ps=0, int i =0, double d=0); NoName(const NoName&); virtual ~NoName(); protected: char *pstr; int ival; double dval; private : void initNoName(const char *ps); }; void NoName::initNoName(const char *ps) { if (ps) { pstr = new char[strlen(ps)+1]; strcpy(pstr, ps); } else { pstr = new char[1]; *pstr = '\0'; } } NoName::NoName(const char *ps, int i, double d) { initNoName(ps); ival = i; dval = d; } NoName::NoName(const NoName &rhs) { initNoName(rhs.pstr); ival = rhs.ival; dval = rhs.dval; } NoName::~NoName() { if (pstr) { delete pstr; pstr = 0; } }
二、初始化
// C++的数据成员中,只允许const static的数据成员在定义时被初始化 /* class Test { private: //int i = 0; // error //const int i = 0; // error //static int i = 0; // error const static int i = 0; // ok }; */ /* class MyMember1 { public : MyMember1(){} // 有默认构造函数 }; class MyMember2 { public : MyMember2(int i){}; // 没有默认构造器 }; // c++ 类的初始化分为隐式初始化、显示初始化、和计算部分(构造函数体内的所有语句) // 隐式初始化包括: 1.调用所有父类的默认构造器 2.调用所有类成员的默认构造器 // 显示初始化,通过成员列表进行的初始化(推荐这样做) // 计算部分,即位于构造器内部的所有语句 // 初始化顺序按照成员声明的顺序,而非初始化列表中的顺序。所以为了方便理解,我们要以成员声明的顺序去进行初始化 class MyClass { public: MyClass(){} // 没有成员列表初始化 private : MyMember1 m1; // ok。能通过 MyMember2 m2; // error。对于没有默认构造器的类成员,只能通过成员列表进行初始化 }; */ /* class MyMember1 { public: MyMember1(int i){} }; // 只能通过列表初始化的方式去初始化的情况: // 1. const(非static)的成员 // 2. 引用成员 // 3. 没有默认构造函数的那些类成员 class MyClass { public: MyClass() :i(100), ri(i), ci(200), m1(3){} private: int i; int &ri; const int ci; MyMember1 m1; }; */
三、extern关键字使用:
1. 在xx.cpp中定义函数和变量 int i10 = 10; void fun(const char* str) { std::cout << "fun(): " << str << std::endl; } 2. 在xx.h中用extern声明这些变量和函数 extern int i10; extern void fun(const char* str); 3. 在别的yy.cpp中包含该xx.h头文件 #include "xx.h" 然后在yy.cpp中直接使用这些变量和函数 int main() { fun("allei"); cout << "i10=" << i10 << endl; return 0; }
四、static关键字
1. static全局变量 * 只能在本文件访问,对于其他文件不可见。其他文件中可以定义同名的变量而不会冲突。 * 保存在全局数据区,默认初始化为0 * 普通全局变量,可以通过extern在其他文件中引用 2. static 局部变量 * 不会随着函数调用结束而释放,而是继续保留上次被调用的值。在全局数据区分配空间,在第一次调用时被初始化,后续调用不再进行初始化 3. static函数 * 和普通函数的区别是只在本文件中可见,不能通过extern的方式被其他文件引用 4. class中的静态成员 * 属于类而非类的对象