前言

期末开始马上就到了,主要考察类的使用和其他常用的C++技术。根据考纲,主要考察的内容为C++特有的内容较多。


类型与值的表现方式

- Type and value of expressions
    - bool int double …
    - Special char types
        wchar_t char16_t char32_t
    - Structure
    - Enum

以上为考纲中描述的内容,bool类型其实就是{true,false},其中非0非空为真,0和空为假。就像使用int类型一样使用也都可以,很好理解。

然后C++中特殊的字符类型:wchar_t表示宽字符,可以表示更多的字符,甚至是外语(中文等),然后在使用的时候,我们需要在定义后加上一个“L”。

char16_t和char32_t表示16位和32位宽字符,在C++11中增加了UTF-16的前缀u和UTF-32的前缀U。

wchar_t wchars = L'你';
char16_t utf16c = u'好';
char32_t utf32c = U'啊';

当然我们在使用的时候,也可以不加前缀,不过要注意编译器的语言是否支持外语。

在结构体和枚举类型中,C++可以有更加方便的写法,就是省略了struct和enum关键字,例如:

struct some{
};
enum a{x,y,z};

struct some s1;//C语言写法
some s2;//C++写法

enum a e1;//C语言写法
a e2;//C++写法

输入输出相关

在使用cout进行输出的时候,我们可以使用格式限定符,例如endl; hax(十六进制); oct(八进制);

int x,y;
cout<<hex<<x<<oct<<y<<endl;

如果我们想把bool类型的{true,false}当做名称输出,可以使用:boolalpha

cout<<boolalpha<<true<<" "<<false;

然后到了经常使用的清空队列,C++中我们可以使用cin.get()来代替C语言的getchar():

while(cin.get()!='\n');

更多cin,cout内容:

【C++学习笔记】输入输出相关成员函数

文件的操作中,C++的文件操作可以使用ofstream和ifstream建立输出流,打开管道对文件进行读入和输出。

#include
int n;
ofstream fout;
ifstream fin;
fout.open("outfile.txt");
fin.open("infile.txt");
fin>>n;
fout<<n;
fin.close();
fout.close();

使用的时候就像是cin,cout一样,只是它们的名字是自己定义的文件输入输出流的名字。注意要关闭文件。


C++关键词和编译

C++新增了很多C没有的关键词:

auto C++11,会根据声明的数据类型进行类型推理,一般模板函数中用到
decltype C++11,用来在编译时期进行自动类型推导,形式为decltype(exp) varName;根据exp表达式进行类型推理
class 声明一个类,或模板函数中的typename的替换
typename 用于引入一个模板参数:typename T;,在模板定义语法中关键字 class 与 typename 的作用完全一样
template 表示声明一个模板,用于template <类型形式参数表>
true/false 表示真和假,代表1和0
bool 声明一个bool类型的变量,它只包含{true/false}
nullptr C++11,空指针常量。NULL一般定义为0,而nullptr一般定义为char*类型
inline 声明内联函数,需要在定义前也加上这个关键字。
and/or/not 在iso646.h中,用于替代&& || !的单词
explicit 用于阻止不应该允许的经过转换构造函数进行的隐式转换的发生,即强制显式转换
this 是一个指向当前对象的指针常量

在编译的时候,我们可以使用一些编译选项:

  • -c:只编译不连接 只生成目标文件 .o文件;
  • -o 指定生成的可执行文件的名称。如果不使用-o选项则会生成默认可执行文件a.out;
  • -std=c++11:使用C++11的标准编译。

语句表达

循环和条件这里就不复习了,在这里还有一个基于范围的for循环

//快速遍历数组
double s[10];
for()...//输入数组
for(double x : s)
{
...
}

此时建立了一个循环变量x,进行遍历数组。

?:表达式:实质就是if else

new运算符中:开辟一个空间new,开辟数组空间:new[]; 

同理delete:delete一个空间,delete一个数组空间。


函数

函数主要是函数探幽部分的函数比较重点:

  • 内联函数:它是声明与定义的集合体,用于代码很少的函数,可以使程序更快。
  • 默认参数:参数缺省。
  • 引用变量:节省空间,相当于别名。
  • 函数模板。

函数模板我们也有一种固定的写法:

首先声明的时候,以template开头,例如:

template <typename T>
void Swap(T & x, T & y);

在定义的时候,把这两行再写一次:

template <typename T>
void Swap(T & x, T & y)
{
    T temp = x;
    x = y;
    y = temp;
}

我们定义的类型T, 应该在模板函数中替换其他类型。

显式具体化模板函数,需要当T为一个特殊类型的时候,调用其他的特殊函数。

例如有一个结构job类型,对其使用显式具象化,它的声明:

template <> void swap<job>(job &a, job &b);

swap<job>中的<job>是可选的,因为函数的参数类型表明,这是job的一个具体化。

所以还可以直接:

template <> void swap(job &a, job &b);

注意:显式具象化的定义只能放在.cpp文件中。


命名空间和static

多个命名空间可以拥有内部同样的名字,我们想要声明一个变量的时候,例如cout:

using std::cout;

在跨文件中,两个链接的文件的名字不能相同,我们可以使用static把它规定为对内的变量。我们还可以使用?extren来声明全局变量。


首先是在类第四部分中有提到的复习部分,就不重复了。

【C++类专题】类继承与类复习

const的使用

我们时常会在成员函数后面加上一个const,是因为这个成员函数不会对private部分的数据进行修改。当不进行修改的时候我们都是用const结尾,例如:

Time operator+(const Time & t) const;

当我们重载的时候,左边不是对象的时候,经常使用friend友元函数。

当我们在参数里使用const的时候,我们不对读进来的这个对象进行修改。

<<重载

我们最常用的<<重载:

friend std::ostream & operator<<(std::ostream & os,const my &t);
std::ostream & operator<<(std::ostream & os,const my &t)
{
    os<<t.val;
    return os;
}

此时左边是cout不是对象,故需要使用友元函数。


静态共享常量

在类里面我们所有的对象共用的一个静态共享变量,我们用static声明:

static int num_string;
//在.cpp文件中,我们需要对它进行定义
int my::num_number=0;

string类编写中注意内容

深拷贝的运用

在默认复制构造函数中,我们需要自己写:

string::string(const string &t)
{
    num_string++;
    len=t.len;
    str=new char[len+1];//重新开辟空间
    str::strcpy(str,t.str);
}

我们重载=号的时候,也要用到深拷贝:

string & string::operator=(const string & st)
{
    if(this == &st)
        return *this;
    delete [] str;
    str = new char[st.len+1];
    std::strcpy(str,st.str);
    return *this;//方便嵌套
}

析构函数写法

我们用new[]开辟了字符串空间,需要释放的时候:

string::~string()
{
    num_string--;
    delete [] str;//注意使用delete []
}

[]的重载

char string::operator[](int i)//non-const
{
    return str[i];
}
const char string::operator[](int i) const//const
{
    return str[i];
}

如果我们不用修改这个值的话,都可以使用const 的形式。


将数据存在预留存储空间中(placenew)

需要使用头文件#include<new>

使用的时候格式:new(<buffer>) somenames;

int *x=new int[100];
int *y;
y=new(x) int;

相当于我把一个变量放在了一个开辟好了的空间上。

当我们使用这样的方法产生对象的时候,我们可以手动调用析构函数。(因为空间不会自动销毁,无法自动启动析构函数)


类继承的写法

class RatedPlayer : public TableTennisClass
{
...
};

注意:我们需要自己写它的构造函数。

虚函数的用法

让构造函数仅仅在定义的类里才使用,我们先看衍生类使用基类的构造函数:

RatedPlayer::RatedPlayer(const string & fn, const string & ln, bool ht, 
unsigned int r) : TableTennisClass(fn,ln,ht)
{
    rating=r;
}

注意这个地方":"后面的格式是:基类构造函数()或衍生类成员();

使用虚函数的时候,基类和衍生类中都需要virtual关键字,并且必须重写两次。使用的时候,必须是引用或指针来调用。


链表

上学期已经考过的内容,会涉及一点点,参照PDF教案和之前的链表专题即可。

教案PDF:https://files.hoyue.fun/documents/A_tutorial_on_linked_lists.pdf

链表专题:

【C专题】结构体和链表

C语言部分链表复习:

【C语言学习之路】期末考试知识复习

这里的一切都有始有终,却能容纳所有的不期而遇和久别重逢。
最后更新于 2024-01-14