sizeof(
返回值为参数数据类型所占字节数的大小。
注:c++文件有输入输出操作时要包含头文件iostream.h
操纵符名 | 含义 |
---|---|
dec | 十进制表示 |
hex | 十六进制表示 |
oct | 八进制表示 |
ws | 提取空白符 |
endl | 插入换行符,并刷新流 |
ends | 插入空字符 |
setprecision(int) | 设置浮点数的小数位数(含小数点) |
setw(int) | 设置域宽 |
eg. cout< auto:编译器通过初始值自动判断变量类型 decltype:定义一个变量与某一表达式类型相同,但不使用它的初值 对象是类的一个实例,类是对象的一种设计。 公有成员:任何外部函数都可以访问 私有成员:只允许本类中的函数访问 保护成员:在继承和派生时对派生类的影响不同 类中成员直接使用成员名相互访问,类外访问公有成员使用 对象名.成员名 进行访问 类的成员函数 注:类的传递通常使用指针传递,提高效率 这是一个C语言的诊断库,assert.h文件中定义了一个可作为标准调试工具的宏函数: assert .下面介绍这个宏函数:assert4.类型关键字auto和decltype
函数
1.内联函数
2.constexpr
eg. constexpr int m{return 20;}
constexpr int c = m();3.带默认参数值的函数
4.函数重载
5.C++系统函数
类和对象
1.面向对象程序的特点
2.类和对象的定义
class 类名称
{
public:
公有成员(外部接口)
private:
私有成员
protected:
保护成员
}
类名称 对象名
class Clock{
public:
int showTime();
int setTime(int h, int m, int s);
private:
int h = 0;
int m = 0;
int s = 0;
}
Clock C1;
– 如果紧跟在类名称的后面声明私有成员,则关键字private可以省略
– 可以在类中和类外给出函数体的实现
– 类外实现时函数名前使用类名加以限定
– 允许函数重载和带默认值
– 内联成员函数也可以被定义,定义要放在类的声明中并用inline声明#include
3.构造函数
– 函数名与类名一致
– 不能定义返回值类型,不能用return
– 可以有形式参数,也可以没有形式参数
– 可以是内联函数
– 可以重载
– 可以带默认值
– 带默认值的构造函数
– 不带实参的构造函数
– 如果程序中未定义构造函数,编译器将自动生成一个默认构造函数,参数表为空
– 如果类内定义了成员的初始值,则使用类内定义的初始值
– 如果类内没有定义成员的初始值,则以默认方式初始化,这样初始化的值是不确定的class Clock{
public:
Clock(int h,int m,int s);
int showTime();
int setTime(int h, int m, int s);
private:
int hour, min, sec;
}
//构造函数的定义,简单初始化的推荐方式
Clock::Clock(int h, int m,int s):
hour(h),min(m),sec(s){
}
int main()
{
Clock C1(12,0,0);//自动调用构造函数
C1.showTime();
return 0;
}
class Clock{
public:
Clock(int h,int m,int s);//构造函数
Clock();//默认构造函数
int showTime();
int setTime(int h, int m, int s);
private:
int hour, min, sec;
}
Clock::Clock():hour(0),min(0),sec(0){
}
int main()
{
Clock C1(12,0,0);
Clock c2;
}
– 一个构造函数委托另一个构造函数来进行初始化
– 保持构造函数的一致性Clock::Clock(int h, int m, int s):
hour(h), min(m) ,sec(s){}
Clock::Clock:Clock(0,0,0){}
– 用一个已经存在的对象去初始化同类型的新变量
– 当我们不对复制构造函数进行定义时,编译器会自动在上述情况发生时生成复制构造函数,做到成员一一对应
– 当我们不想使两个对象一一对应时,就要自己定义复制构造函数
– 复制构造函数的形参为本类的对象的引用,作用是利用一个已经存在的对象去初始化同类型的新对象
– 在函数形参的参数传递和返回时都会调用复制构造函数,用来构造临时无名对象做参数传递class 类名{
public:
类名 (形参);//构造函数
类名(const 类名 &对象名);//复制构造函数
}
类名::类名(const 类名 &对象名)
{函数体}
Clock() = default;//指示编译器使用默认构造函数
Clock(const Clock &C) = delete;//指示编译器不生成复制构造函数
4.析构函数
Clock::~Clock(){}
5.类的组合
– 不仅要负责本类中基本类型成员的数据的初始化,还要对对象成员初始化
– 组合类对象的构造次序:首先对构造函数初始化列表中列出的成员(包括基本类型成员和对象成员)进行初始化,初始化次序是成员在类体中定义的次序;处理完初始化列表之后,再执行构造函数的函数体
– 对象成员构造函数调用顺序:按对象成员的调用顺序,先声明者先构造
– 初始化列表中未出现的成员对象,使用默认构造函数进行初始化类名::类名(对象成员所需的形参,本类成员形参):
对象1(参数),对象2(参数),……
{
//函数体其他语句
}
class Point{
public:
Point(int x1, int y1):x(x1),y(y1){}
private:
int x = 0;
int y = 0;
}
class Line{
public:
Line(Point p1, Point p2):a(p1),b(p2){}
private:
Point a;
Point b;
}
6.前向引用声明
– 在提供一个完整的类声明之前,不能声明该类对象,也不能在内联成员函数中使用该类对象
– 当使用前向引用声明时,只能使用被声明的符号,而不能涉及类的任何细节class A;
class B
{
public:
void f(A a);
}
class A
{
public:
void f(B b);
}
7.UML
8.结构体
9.联合体
union Mark
{
char grade;
bool pass;
int percent;
}
//无名联合体
union
{
int i;
float k;
}
10.枚举类
– 强作用域:作用域在枚举类,使用必须用类名
– 转换限制
– 可以指定底层类型//enum class Type:char{a,b,c};
//enum class type{a=1,b,c};
enum class Type{a,b,c};
enum class type{a,b,c};
//usage
Type s = Type::a;
type w = type::a;
s == w;//错误,不能直接比较
数据的共享与保护
1.类的静态数据成员
2.类的静态函数成员
class Point
{
public:
static int count;
static void showCount();
}
Point::showCount()
{
cout<<count<<endl;
}
Point::count = 0;
Point::showCount();
3.类的友元
– 友元函数:在类声明中由关键字friend修饰的非成员函数
– 友元类:这个类的所有成员都能访问另一类的私有成员class Point
{
public:
friend float ab(const Point &a, const Point &b);
private:
int x;
int y;
}
float ab(const Point &a, const Point &b)
{
return a.x - b.x;
}
class A
{
public:
friend class B;
private:
int x;
int y;
}
class B
{
public:
int set(int i);
private:
A a;
}
B::set{int i}
{
a.x = i;
}
4.共享数据的保护(const)
– 常数据
– 常成员函数
– 既能保证安全性,又能保证高效执行,避免参数在参数传递时重复初始化。相当于“只读”
– 常见的应用:复制构造函数
– 不更新对象的数据成员
– 类型说明符 函数名(参数表) const
– const关键字可以被用于参与对重载函数的区分
– 通过常对象只能调用它的常成员函数class A
{
public:
void print();
void print() const;
private:
int a = 0;
}
void A::print()
{
a = a + 1;
cout<<a<<endl;
}
void A::print() const
{
cout<<a<<endl;
}
void main()
{
A a1;
const A a2;
a1.print();
a2.print();
}
class A
{
public:
A(int i);
private:
const int a;
static const int b;
}
const int A::b = 10;//类外对静态常变量做初始化
A::A(int i): a(i){}//构造函数,注意:只能在函数体外对常变量进行初始化
数组和指针
1.基于范围的for循环
int arr[3] = {1,2,3};
for(auto &e : arr)
{
e = e + 1;
cout<<e<<endl;
}
2.动态内存分配与释放
– new 类型名(初始化参数列表)
– delete 指针
– 指针必须是new操作返回的地址3.申请和释放动态数组
– 数组长度可以是任何整型表达式,在运行时计算
– 必须有[]
– 指针必须是new分配的数组首地址指针
– 这个指针是指向行的指针,当指针+1时指向的位置跳跃一整维Point *p1 = new Point(1,2);
int *p2 = new int[5];
int (*p3)[8][5] = new int[3][8][5];
delete p1;
delete[] p2;
delete[] p3;
4.智能指针
– 不允许多个指针共享资源,可以用标准库中的move函数转移指针
– 多个指针共享资源
– 可以复制share_ptr,但其构造和释放对资源不产生影响5.vector对象
– 封装任何类型的动态数组,自动创建和删除
– 数组下标越界检查
– vector数组对象名不表示数组首地址//参数为vector引用
double average(const vector<double> &arr)
{
double sum = 0;
for(int i = 0; i < arr.size; i++)
{
sum = sum + arr[i];
cin>>arr[i]//这里是vector对[]进行了运算符重载
}
return sum;
}
vector<int> arr(3) = {1,2,3};
for(auto e : arr)
{
cout<<e<<endl;
}
for(auto e = arr.begin(); e != arr.end(); e++)
{
cout<<e<<endl;
}
6.对象复制与移动
– 指针复制的结果是将指针空间所存地址复制到新的对象中去,两个对象中的指针成员指向同一块内存空间,这会导致析构出错。ArrayPoint::ArrayPoint(const ArrayPoint &v)
{
size = v.size;
point = new Point[size];
for(int i = 0; i < size; i++)
point[i] = v.point[i];
}
7.移动构造
//这里 && 表示右值引用,即将消亡的值是右值
ArrayPoint::ArrayPoint(const ArratPoint &&v):points(v.points)
{
//C++中的空指针用nullptr表示
v.points = nullptr;
cout<<"Move constructor"<<endl;
}
8.string类
– string()
– string(const char *s)
– string(const string &s)
– s + t 字符串的拼接
– s = t
– s == t
– s != t
– s < tstring s1 = "abc";
string s2 = "def";
string s3 = s1 + s2;
bool s = s1 < s2;
//string类的长度可以自动扩展
string s;
cin>>"string is:">>s;
cout<<"length is:"<<s.length()<<endl;
– getline(输入方式,目标存储位置,[输入结束标志])
– getline(cin, s) getline(cin,s,’+’)附录:
– 如果这个宏函数形式的参数(expression)等于零,也就是说参数的表达式等价于false,那么就会有一条消息会被写入到标准错误设备,并且调用abort()函数来终止程序的运行;
这条特殊消息的显示依赖于特定库的实现,但是至少包括: 错误参数的陈述,源文件的名称,发生错误的行号;
– expression可以是一个待计算的表达式,如果表达式的运算结果是0,这将导致断言失败(assertion failure)并终止程序;