Skip to content

第一章 前言

第二章 基础语法

1、输入输出流

cpp
// 一些基本用法
cout << " i = " << i << " (decimal )\n";

cout << " i = " << oct << i << " (octal )\n";

cout << " i = " << hex << i << " (hexadecimal)\n";

cout << " i = " << dec << i << " (decimal )\n";




// 操纵符的作用域直到操纵符下一次改变为止。setw除外、
// setw 用来设置域宽,setw设置的域宽值有剩余,setfill用来设置剩余位的填充字符
cout<<setfill('*')<<setprecision(4);



// 使输出 靠 输出域 的左边 或者 右边
cout<<left<<setw(10)<<"karen"<<right<<setw(6)<<a<<'\n';



// 操纵符 setprecision 和fixed联用,表示设置小数点之后的位数。
cout<<fixed
cout<<setfill('*')<<setprecision(2);


//第三种写法
cout<<fixed<<setprecision(2);

2、C++增强类型

逻辑类型:bool 枚举类型:enum 引用类型:& 结构体:struct

3、引用

  • 引用是一个变量的别名。
  • 引用和其引用的变量占用同一段内存空间。
  • 引用声明时必须被初始化,以后不能被更改。
  • 引用的值改变即等价于被引用的变量的值发生的改变。

4、new/delete

cpp
// 运算符new使用语法格式化:
new datatype

int* int_ptr;
int_ptr=new int;

// 运算符 new[ ] 使用语法格式:
new datatype[num]

int* int_ptr;
int_ptr=new int[50];


// 运算符 delete 释放由new分配的空间语法格式:

delete pointername;
delete int_ptr;

// 运算符delete[ ] 释放由new[ ]分配的空间语法格式:

delete[ ] pointername;
delete[ ] int_ptr;
  • delete只能释放new动态申请的空间(malloc等的不行)
  • 普通变量系统在程序结束(或函数调用结束后)会自动回收占用的空间,new申请的空间在堆上,系统不会回收相应空间
  • delete之后,指针本身和指针指向的空间的数据不会清空,除非再次写入数据。new的那段空间相当于被加上不能被占用的标记,delete相当于清除了标记,那块地址还可以用指针访问,但有风险了,因为随时就有被占用的可能

5、auto关键字 (C++11新增)

6、类型转换

  • static_cast

  • const_cast

  • dynamic_cast

  • reinterpret_cast

  • static_cast : 用于一种类型到另一种类型或具有继承关系的合理的转换 语法格式: static_cast<new_type> (expression)

  • const_cast: 主要作用是移除类型的const属性,常用于修改指针类型。 语法: const_cast<new_type> (expression)

  • reinterpret_cast : 该函数将一个类型的指针转换为另一个类型的指针 将指针值转换为一个整型数,但不能用于非指针类型的转换

  • dynamic_cast:与static_cast相对,是动态转换。这种转换是在运行时进行转换分析的,并非在编译时进行,区别于前3个类型的转换操作。 该函数只能在派生类对象的指针之间或引用之间进行类型转换进行转换时,会根据当前运行时类型信息,判断类型对象之间的转换是否合法。 语法格式:      dynamic_cast<new_type> (expression)

7、String

cstring

cpp
char cityname1[20],cityname2[20];
cout<<"请输入一个城市名字:"<<endl;
cin>>cityname1;
cout<<"你的输入是"<<cityname1<<endl;

// 直接cin 以Tab 空格回车为分隔符

cin.getline(string_var1,Max_Characters+1);

char question[20],answer[20]; 
cin.getline(question,20);
// 使用getline 以回车作为分隔符

C-String-to-Number 函数

  • 函数 atoi 和 atol 是把数字字符串转换为整型值
  • 函数 atof 把数字字符串转换为double类型的值

标准string

cpp
#include <string>
using namespace std;
string s1;
string s2=“China”;
string s3=s2;
string s4(10,’x’);





1.字符串比较
根据“当前字符特性”将字符按字典顺序进行逐一得 比较。字典排序靠前的字符小, 比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小

2.字符串长度
size()和length():返回string对象的字符个数,他们执行效果相同。

3.连接
s3 = s1 + s2;
4.插入
string str="to be question";
string str2="the ";
string str3="or not to be";
str.insert(6,str2);                 // to be (the )question
str.insert(6,str3,3,4);             // to be (not )the question
str.insert(10,"that is cool",8);  // to be not (that is )the question
str.insert(10,"to be ");   // to be not (to be )that is the question
str.insert(15,1,':');       // to be not to be(:) that is the question
str.insert (str.end(),3,'.');   // to be, not to be: that is the question(...)

5.提取子串
string s1 = "Ray Dennis Steckler";
string s2,s3;
s2=s1.substr (4,6); // Dennis
s3=s1.substr(0,3)   // Ray

6.查找
f=s1.find(s2);

第三章 函数增强

1.传参

  • 值传参
  • 地址传参
  • 引用传参

2.引用传参

传递引用参数时,在调用函数中引用像变量那样直接使用。

cpp
void fun (const int &cref)
{
  cout<<cref/15; //NO PROBLEM
  cref++; //ERROR! Cannot modify a const reference.
}
  • 引用参数可以和 #const 连用避免在调用函数中无意把参数值改变。
  • 使用指针作为函数参数时,函数调用时我们需要前面加上&取地址运算符。

3.对比

cpp
Swap(&x,&y);
void Swap(int* a, int* b)
{
  int t;
  t=*a;
  *a=*b;
  *b=t;
}


Swap(x,y);
void Swap(int& a, int& b)
{
  int t;
  t=a;
  a=b;
  b=t;
}

==引用作为函数参数时比较指针的优点:== ==代码清晰,不必时刻记住 * 的使用;== ==不必记住传递实参的地址;== ==使用引用时,不必新开辟内存空间;== ==当传递的参数是某个对象的引用时,引用的效率会是很重要的方面。==

4.带参宏

5.内联函数

6.带缺省参数值的函数

  • C++允许自定义函数中的形参值有初始默认值

7.重载函数

8.函数模板

cpp
template <typename T>
T Fun(T n) {
	//
}
template <typename T>
T Fun(T n) {
	//
}

第四章 类和对象

1.构造函数

  • 如果程序中未声明,则系统自动产生出一个默认形式的构造函数
  • 允许为内联函数、重载函数、带默认形参值的函数
  • 系统提供缺省的构造函数默认为public的,存在下列两种情况:
  1. 只有类中没有任何构造函数的定义或声明,系统才会提供缺省构造函数,如果系统提供了某种有参构造函数,但仍需要使用无参构造函数即缺省构造函数,此时需要程序员在类中自己定义缺省构造函数。
  2. 如果类中存在构造函数,但构造函数为private,此时系统也不会提供缺省构造函数。

2.拷贝构造函数

==拷贝构造函数,顾名思义,即用已经存在的类的对象去构造一个新的对象,两个对象的数据成员值是完全相同的。==

拷贝构造函数的函数原型格式为:

cpp
BankAccount(BankAccount&);
BankAccount(const BankAccount&);


BankAccount account1(100,0.3);
BankAccount account2(account1);
  • 如果类中没有定义拷贝构造函数,系统会自动提供一个拷贝构造函数。
  • 这个构造函数执行的功能是:用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。

拷贝构造函数被调用的3种情况

  1. 用已经存在的对象初始化另一个对象时;
  2. 对象作为实参传递给形参时;
  3. 对象作为函数返回值时。

深拷贝构造函数 当类中包含指针类型的数据成员时,需要程序员自行实现一个完整的拷贝构造函数,否则使用系统提供的拷贝构造函数会带来意想不到的错误结果。

3.转换构造函数

==构造函数还提供了一种自动类型转换的功能,即把一种类型转换为该类类型。==

4.析构函数

  • 完成对象被删除前的一些清理工作。
  • 在对象的生存期结束的时刻系统自动调用它,然后再释放此对象所属的空间。
  • 如果程序中未声明析构函数,编译器将自动产生一个默认的析构函数。

格式: ~类名( );

  • ==析构函数不允许有参数,所以一个类中只能有唯一的析构函数。==
  • 一般地,系统会自动提供析构函数,并在对象生存期到前自动调用析构函数,但是我们也可以根据需要来定义自己的析构函数。

5.const与类

第五章 派生与继承

1.派生类的构造函数

cpp
派生类名(参数总表): 基类名1(参数表1),…,基类名m (参数表m),  
成员对象名1(成员对象参数表1),…,成员对象名n(成员对象参数表n)  
{
	派生类新增成员的初始化;  
}
  • 派生类中需要声明自己的构造函数
  • 构造函数不能被继承
  • 派生类的构造函数需要注意3部分:
  1. 对继承来的基类成员的初始化
  2. 对本类中新增成员进行初始化
  3. 内嵌成员对象的初始化(即类的数据成员是其他类的对象)
  • 在派生类对象的成员中,从基类继承来的成员它们的初始化由派生类的构造函数隐含调用基类构造函数进行初始化
  • 内嵌成员对象则隐含调用成员所属类的构造函数进行初始化
  • 派生类新增的数据成员由派生类在自己定义的构造函数中进行初始化。

2.派生类构造函数调用规则

单继承的构造函数调用顺序 单继承时,派生类构造函数调用的一般次序如下:

  1. 调用基类构造函数。
  2. 调用内嵌成员对象的构造函数,调用顺序取决于它们在类中定义的顺序。
  3. 派生类自己的构造函数。

3.虚基类

  • 用于有共同基类的场合
  • 以virtual修饰说明基类

例:class B1:virtual public B

作用

主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题. 为最远的派生类提供惟一的基类成员,而不重复产生多次拷贝

注意

在第一级继承时就要将共同基类设计为虚基类

虚基类的调用

  • 建立对象时所指定的类称为最(远)派生类。
  • 虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
  • 在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的默认构造函数。
  • 在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略。从而保证对虚基类子对象只初始化一次。
  • 在一个成员初始化列表中,同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。
  • 虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。因为一个基类可以在生成一个派生类作为虚基类,而在生成另一个派生类时不作为虚基类。

4.

第六章 多态与虚函数

1.多态性

  • 多态性是面向对象程序设计的重要特征之一。
  • 多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为。
  • 多态的实现:
  1. 函数重载 ->静态联编
  2. 运算符重载 ->静态联编
  3. 虚函数 ->动态联编

2.静态连编与动态联编

  • 联编:程序自身彼此关联的过程,确定程序中的操作调用与执行该操作的代码间的关系。
  • 静态联编:联编过程出现在编译阶段,用对象名或者类名来限定要调用的函数。
  • 动态联编(迟后联编、滞后联编):绑定过程工作在程序运行时执行,在程序运行时才确定将要调用的函数。

3.动态联编

  • 在编译、链接过程中无法解决的联编问题,要等到程序开始运行之后再来确定。动态联编的主要优点是提供了更好的编程灵活性、问题抽象性和程序易维护性,但是与静态联编相比,函数调用速度慢,因为动态联编需要在程序运行过程中搜索以确定函数调用(消息)与程序代码(方法)之间的匹配关系。
  • 动态联编由虚函数来实现。
  • ==形参为基类的引用==

4.虚函数

虚函数定义

  • 虚函数允许程序员在基类中定义,在其每一个派生类中重新定义。
  • 关键字virtual只能在函数声明时使用。
  • 虚函数可以像其他函数一样被继承。
  • 在派生类中重新定义函数时,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体。

虚函数使用

  • 当在类的层次结构中声明了虚函数以后,并不一定就能实现运行时的多态性,必须合理调用虚函数才能实现动态联编。
  • 只有在程序中使用基类类型的指针或引用调用虚函数时,系统才以动态联编方式实现对虚函数的调用。
  • 如果使用对象名调用虚函数,系统仍然以静态联编方式完成对虚函数的调用,也就是说,用哪个类说明的对象,就调用在哪个类中定义的虚函数。

5.纯虚函数

C++规定,对于类族中无法实现的成员函数,可以定义为纯虚函数,其具体的实现由其派生类来完成。

纯虚函数:

  • 只有函数声明,没有函数实现的函数。
  • 从语法上讲,纯虚函数是在虚函数的后面加上“=0”,表示该虚函数无函数体
  • 这里的“=”并非赋值运算。
  • 纯虚函数为类的继承提供了连续的接口。 定义格式
cpp
class <class-name>
{
    virtual <type> <function-name>(<arguments>)=0;
 //……
}

注意:在构造函数和析构函数中不能调用纯虚函数。 只有虚函数才可能是纯虚函数 即非虚函数或普通函数都不能定义成纯虚函数

6.抽象类

  • 如果一个类中至少有一个纯虚函数,则这个类为抽象类。
  • 如果派生类中没有再对基类中的纯虚函数进行重定义,则派生类也是抽象类
  • 不能定义抽象类的对象,但可以定义抽象类的指针和引用。
  • 在继承层次结构中,抽象类的作用是为派生类提供一个基本框架和公共的对外接口,一般作为基类存在