一、 #ifndef/#define/#endif的使用
#ifndef/#define/#endif 防止该头文件被重复引用,“被重复引用”是指一个头文件在同一个cpp文件中被include了多次,这种错误常常是由于include嵌套造成的。比如:存在a.h文件#include "c.h"而此时b.cpp文件引用了#include "a.h" 和#include "c.h"此时就会造成c.h重复引用。
造成重复引用的后果,只是增加了编译工作的工作量,不会引起太大的问题,仅仅是编译效率低一些,但是对于大工程而言编译效率低下将是严重的问题。为了良好的编程习惯
建议每个类都加入#ifndef/#define/#endif标志。
例子:
#ifndef PERSONAL
#define PERSONAL
class Personal
{
}
#endif
二、类模板 template <class T>
比如定义了某些类,需要对这些类进行相应的数据操作,使用类模版来定义操作类,赋予不同的数据类型即可进行操作。
template<class T>//声明类模版,class定义虚拟类型,T为虚拟类型名(在使用时需要具体指定类型,至于虚拟类型名是什么自己指定)
class Database {
public:
Database();
void run();
private:
fstream database;
char fName[20];
ostream& print(ostream&);
void add(T&);//使用虚拟类型名T进行add操作,在该成员函数定义的时候也需要使用类模版的形式,如下代码
bool find(const T&);
void modify(const T&);
friend ostream& operator<<(ostream& out, Database& db) {
return db.print(out);
}
};
template<class T>//声明模版类
void Database<T>::add(T& d) {//数据类型为虚拟类型T(红色标出为主要两点,所属类和函数形参都需要用虚拟类型T)
database.open(fName,ios::in|ios::out|ios::binary);
database.clear();
database.seekp(0,ios::end);
d.writeToFile(database);
database.close();
}
在声明好类模版之后,需要调用类模版,调用如下:
Database<int> data_int;//需要为虚拟类型赋予实际的类型名(虚拟类型实例化,给予实际类型)
int a=2;
data_int.add(a);
三、friend ostream &operator<<(ostream &stream, const Date& dt);
c++中有个friend关键字,它能让被修饰的对象冲破本class的封装特性,从而能够访问本class的私有对象。简单来讲,就是:
如果你在A类中,申明了函数func()是你的friend,那么func()就可以使用A类的所有成员变量,无论它在什么地方定义的。
如果你在A类中,申明了B类是你的friend,那么B类中的方法就可以访问A类的所有成员变量。
class A {
public:
A() {
password = 1111;
birthday = 808;
}
~A() { }
friend int func(A a); // 向c++表示,int func(A a)是我的朋友,所以它可以使用我的所有东西。
friend class B; // 向c++表示,class B是我的朋友,所以它可以使用我的所有东西。
private:
int password;
int birthday;
};
运用friend重载 << 或者 >>操作
friend ostream &operator<<(ostream &stream, const Date& dt);//利用friend特性对<<操作符进行了重载,函数返回值为ostream&类型,赋予了新的功能。operator是操作符的意思,后面紧跟相应的操作符(相当于“operator 对应操作符”就相当于一个函数名)
friend ostream& operator<<(ostream& out, Database& db) {
return db.print(out);//重载<<操作符,函数<<操作符可以访问类中的所有成员变量(无论定义在哪)调用db对象中的print函数执行输出;
}
四、getline的使用
getline(istream &in, string &s)
从输入流读入一行到string s
•功能:
–从输入流中读入字符,存到string变量
–直到出现以下情况为止:
•读入了文件结束标志
•读到一个新行
•达到字符串的最大长度
–读到一行赋给s返回true,如果getline没有读入字符,将返回false,可用于判断文件是否结束
五、标准转换运算符reinterpret_cast
reinterpret_cast <new_type> (expression) // reinterpret_cast <另一种类型> (原类型,原类型大小(sizeof(类型名)))
reinterpret_cast是强制类型转换符!他是用来处理无关类型转换的,通常为操作数的位模式提供较低层次的重新解释!但是他仅仅是重新解释了给出的对象的比特模型,并没有进行二进制的转换!他是用在任意的指针之间的转换,引用之间的转换,指针和足够大的int型之间的转换,整数到指针的转换,通常可将*int强制转为*char用于对整数的存储和表示。
int *pi;
char *pc = reinterpret_cast<char*>(pi,sizeof(int));
但是要注意的是,他并没有进行二进制的转换,pc指向的真实对象其实还是int,不是char.