格式化带小数点数字
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2); // 保留小数点后2位
枚举
enum Direction {NORTH, SOUTH, EAST, WEST};
// 等价于 enum Direction {NORTH=0, SOUTH=1, EAST=2, WEST=3};
引用与const
-
希望函数能改变变量的值就用引用&。
-
常引用调用参数更有效率,即const Class& object1。
-
const要么不使用,要么应该使用的地方都使用。
-
返回引用的函数:
double& sample(double& number) { return number; } double m = 1; sample(m) = 2; // 2 -> sample()
-
函数前面用const表示返回值为const,后面用const表示函数不可修改class的成员(仅可读)。
assert宏
#define NDEBUG // 关闭assert调试
#include <cassert>
// ...
assert((0 < number) && (number < 100)); // 检验前提条件 0<number<100
compute(number);
模板类
使用任何数据类型来代替尖括号中的基本类型,以便产生该数据类型的类。
vector<int> v;
操作符重载(+,==,<<等)
class Money{...};
// 第一个const表示返回值不能被修改,称为常量返回值
const Money operator +(const Money& m1, const Money& m2);
bool operator ==(const Money& m1, const Money& m2);
// 作为成员函数的操作符重载
class Money{
public:
// 调用对象就是第一个操作数
const Money operator +(const Money& m2) const;
bool operator ==(const Money& m2) const;
};
// 重载"<<"、“>>”
class Money{
public:
friend ostream& operator <<(ostream& os, const Money& m);
friend istream& operator >>(istream& is, Money& m);
};
ostream& operator <<(ostream& os, const Money& m){
// ...
return os;
}
友元函数
// 不是类的成员函数,但能直接访问类的私有成员
class Money{
public:
friend const Money operator+(const Money& m1, const Money& m2);
friend bool operator ==(const Money& m1, const Money& m2);
};
函数的返回值方式
- 返回一般的值,对应的函数声明为T f();
- 返回常量值,对应函数声明为const T f();
- 返回引用,对应的函数声明为T& f();
- 返回常量引用,对应函数声明为const T& f();
get()、getline()
// get取字符
cin.get(ch);
// getline作成员函数
cin.getline(line, 80);
// getline作引用函数
getline(cin, line); // 遇'\n'停止
getline(cin, line, '?'); // 遇'?'停止
new创建动态变量
Type *p;
p = new Type;
delete p;
// 动态数组
int* a;
a = new int[Size];
delete [] a;
继承和虚函数
-
公有继承
- 纯虚函数 =>继承的是__接口__
- 虚函数 =>继承的是__接口+缺省实现__
- 非虚函数 =>继承的是__接口+强制实现__
-
不要重新定义一个继承自基类的非虚函数。
-
在声明需要重写的函数后,加关键字__override__
命名空间(一个完整的接口文件)
将辅助函数隐藏在命名空间中(实现文件time.cpp),而非接口文件(time.h)中。
// time.h 类DigitalTime的接口(完整)
#ifndef DTIME_H
#define DTIME_H
#include <iostream>
using std::istream;
using std::ostream;
namespace DTime
{
class DigitalTime
{
public:
DigitalTime(int theHour, int theMinute);
DigitalTime(); // 初始化为0:00
DigitalTime(const DigitalTime &time); // copy构造函数
// 取值函数
int getHour() const {return hour;} // 内联
int getMinute() const;
// 赋值函数
void advance(int minutesAdded);
void advance(int hoursAdded, int minutesAdded);
// 虚函数:直到函数被调用时获得对应于调用对象的函数实现
virtual double timeCost() const override;
// 纯虚函数:不给出函数定义的虚函数(只提供接口)
virtual void draw() = 0;
// 操作符重载
double &operator[](int index); // 索引
friend bool operator==(const DigitalTime &time1, const DigitalTime &time2);
friend istream &operator>>(istream &is, DigitalTime &time);
friend ostream &operator<<(ostream &os, const DigitalTime &time);
// 析构函数
virtual ~DigitalTime();
private: // 使用protected可使继承类直接使用hour、minute等变量,而无需调用取、赋值函数
int hour;
int minute;
};
} // namespace DTime
#endif
推荐使用未命名命名空间代替static修饰词,将一个名字局限于编译单元内。
// time.cpp 类DigitalTime的实现文件
// ...
namespace{
// ... 局限在time.cpp的辅助函数
}
namespace DTime
{// ... 类成员函数}
文件流
// 读文件,等价于ifstream fin("path");
ifstream fin;
fin.open("path");
// 写文件,等价于ofstream fout("path", ios::app)
ofstream fout;
fout.open("path", ios::app); // ios::app 添加内容
// 检查文件输入/输出
if(fin.fail()){
cerr << "open failed.\n";
exit(1);
}
向上转换和向下转换
// 向上转换(切片)
Base base;
Derived derived;
base = derived;
// 向下转换(dynamic_cast仅用于指针)
Base *base;
base = new Derived;
Derived *derived = dynamic_cast<Derived*>(base);
函数模板及类模板
// 函数模板
template<class T> // 声明及定义都要包含模板前缀
void swap(T &v1, T &v2){
// ...
}
// 类模板
template<class T>
class Pair{
public:
Pair();
Pair(T v1, T v2);
// ...
};
template<class T> // 成员函数
Pair<T>::Pair(T v1, T v2){// ...}
容器与迭代器
// 容器
vector<int> container;
for (int i = 0; i< n; i++)
// 容器常见的成员函数
container.push_back(element);
container.pop_back();
container.push_front(element);
container.erase(container.begin(), container.begin()+2); // 删除前两个元素
container.size();
// 迭代器
iterator p;
for (p = container.begin(); p != container.end(); p++)
process *p;
// C++11
for (auto p = container.begin(); p != container.end(); p++)
process *p;
for (auto element : container)
process element;
c++接口(抽象类)
C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念。
如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。如果一个 ABC 的子类需要被实例化,则必须实现每个虚函数,这也意味着 C++ 支持使用 ABC 声明接口。
// 基类
class Shape
{
public:
// 提供接口框架的纯虚函数
virtual int getArea() = 0;
void setWidth(int w){
width = w;
}
void setHeight(int h){
height = h;
}
protected:
int width;
int height;
};
// 派生类 getArea()的不同实现
class Rectangle: public Shape
{
public:
int getArea(){
return (width * height);
}
};
class Triangle: public Shape
{
public:
int getArea(){
return (width * height)/2;
}
};