本文全部内容基于西安电子科技大学潘蓉老师的《面向对象程序设计》课程记录而成
C++是C的超集,有STL,支持OOP和泛型编程(Generic Programming)
C++特色:
- 有封装;
- 可以通过泛化、继承来实现程序的重用和多态。泛型可以编写一般化、可重用的算法并且对效率没有影响;
- 可以对函数、运算符进行重载。
泛型可以处理不同数据类型的数据。泛型程序可通过模板来实现,模板实现了数据类型、函数定义的参数化。
关于 #include
#include <...> // 尖括号写的是 C++ 自带的。编译器会去 include 目录进行搜索
#include "..." // 一般自己写的。编译器首先到当前工作目录中去查找,再去 include 寻找
namespace
- STL 中的东西都是在 std 中声明的,使用类等之前需要指明其所在的命名空间。
using namespace std; // 整个都用 std
using std::cout; // 只且只有 cout 可以直接写出来而不用带命名空间
using std::cin; // 同上
- 命名空间可防止重名冲突
命名空间的定义和使用
namespace ns1 { // declear
int inflag;
void g(int);
}
namespace ns2 {
int inflag;
}
//-------------------------
ns1::inflag = 2; // use
ns2::inflag = 1;
//-------------------------
using ns1::inflag;
inflag = 666; // in ns1
ns2::inflag = 123; // in ns2
ns1::g(123); // call. namespace required.
//-------------------------
using namespace ns1;
g(456); // call. without namespace, for having using above.
C++也可以用没名字的命名空间。
这样的空间中的内容无法在其他文件中进行访问,只能在本文件中使用——从声明处开始直到其所在源文件结束处。
int i = 666;
namespace {
int i = 123;
}
int main () {
cout << i;
}
// 会报错,【多重定义】
CPP 输入输出
IO 由 I/O 流类库提供,cin 和 cout 是两个对象,分别代表标准输入输出设备。
cout
cout 是一个输出流类的对象,“输出流”指的是从内存向输出设备流动的数据流。cout做的事情就是将要输出的数据插入到输出流对象中。也被称为“插入操作”。
cout<<exp1<<exp2<<...<<endl; // endl,换行。"<<"是“输出运算符”或“插入运算符”
cin
标准输入流对象。输入流是从输入设备流向内存的数据流。
cin是从输入流对象中提取数据,也称为“提取操作”。
cin>>var1>>var2>>...<<varn; // “>>”:“输入运算符”/“提取运算符”
使用 const 定义常量
C 中使用宏替换来定义常量。
定义使用 #define 进行,在预编译时进行字符置换,又称“宏替换”
#define PI 3.14
C++ 使用 const 定义常量
const <datatypeName> <constName> = <expression>; // 常量在定义时进行初始化
const int maxLine = 1000; // 初始化是常量赋值的唯一方式
maxLine = 123; // Wrong.
#define VS const
-
#define 无类型,const 有;
-
一些 IDE 仅能检查、调试 const;
-
使用 #define 可能出现奇怪的错误,如:
#define pow a+b pow*pow; // 被换成 a+b*a+b,显然与设想不符
函数原型声明
若进行函数调用的位置在该函数定义位置之前,则须在调用前进行函数声明。
// 函数类型 函数名 (参数类型 [参数名称], ...)
函数重载
在同一作用域中使用同一函数名定义多个函数。这些函数的参数类型和个数(至少有一个)不同。只有返回值类型不同并不可以。
int add(int a, int b);
double add(double a, double b);
函数模板
引入 template 的目的在于:解决大量使用重载时,会产生大量类似的多余代码的问题。
适用于函数体相同、函数参数个数相同、类型不同的情况。
template<typename T 或 class T> // T 是类型名
template<typename T>
T max(T a, T b) {
return (a>b)?a:b;
}
函数模板不是确定的函数,编译器不会将模板本身变成指令。
编译器遇到与模板匹配的函数调用时,自动生成一个专用的重载函数,该函数的函数体与函数模板相同,但涉及类型的部分都被改变了。
例如:
int max(int a, int b) {
return (a>b)?a:b;
}
这是一个“模板函数”,意为"从模板产生的函数",是函数模板的一个实例,只能处理一种类型的数据。
函数模板是模板,模板函数是函数。
使用多个类型的参数
// template <class T1, class T2, class T3>
template<class T1, class T2>
T1 max(class T1, class T2) {
return (a>b)?a:(T1)b; // 返回时需要对 b 进行类型转换
}