谭浩强《C++面向对象程序设计》知识点总结
C/C++基本数据类型长度
目录
C++的初步知识
- C++创始人:Bjarne Striustrup
- 输出:
cout<<
,其中cout
为输出流对象,<<
是“插入运算符”,两者构成cout语句。 - 输入:
cin>>
,其中cin
为输入流对象,>>
是“提取运算符”,两者构成cin语句。
注意:程序中有输入与输出时,必须使用
#include<iostream> // 使用输入与输出时必须使用的头文件
using namespace std; // 表示要用到命名空间std中内容
int main()
{
...
}
tips:
endl
是输出时的控制符,与“\n”作用相同。- 在例1.3中,注意输入的两个数据间用一个或多个空格间隔,不能以逗号或其他符号间隔。否则,会使后面变量有不可预见的值。
- “.”是一个“成员运算符”,把对象和成员联接起来。
- 如果要指定输出所占的列数,可以用控制符
setw
设置(使用setw
必须包含头文件iomanip.h
)。setw(5)
表示后面一个输出项预留5列,如果输出项超过,则按实际长度输出;如果不够,则数据向右对齐。
- 用
const
定义常变量。 - 函数模块:
template < typename T >
通用函数定义
或
template < class T >
通用函数定义
- 字符串变量:
#include <string>
string string1; // 定义string1为字符串变量
string string2 = "China"; // 定义string2同时对其初始化
类和对象
构造函数(Constructor)
对象的初始化
- 类的数据成员是不能再声明类时初始化的。下面写法错误:
class Time
{
hour = 0;
minute = 0;
sec = 0;
};
原因:类并不是一个实体,而是一种抽象类型,并不占存储空间,显然无法容纳数据。如果一个类中所有的成员都是public,则可以在定义对象时对数据成员进行初始化(如下代码)。若限制为private或protected则不能用这种该方法。
class Time
{
hour = 0;
minute = 0;
sec = 0;
};
Time t1 = {14, 56, 30};
注:在一个花括号内顺序 列出各公用数据成员的值,两个值之间用逗号分隔。
构造函数的作用
- 在建立时自动执行,名字必须与类名相同,不具有任何类型,不返回任何值。
- 可以在类内定义构造函数,也可以在类外定义构造函数。在类外定义构造函数,需要加上类名和域限定符
::
。 - 使用说明:
-(1)在类对象进入其作用域时调用构造函数。
-(2)如果用户自己没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数,不执行初始化操作。
带参数的构造函数
- 不带参数的构造函数,在函数体中对各数据成员赋初值时,每一个对象都得到同一组初值。
- 采用带参数的构造函数,在调用不同对象的构造函数时,从外面将不同的数据传递给构造函数,以实现不同的初始化。
- 一般格式:
构造函数名(类型1 形参1, 类型2 形参2,...)
类名 对象名(实参1, 实参2,...);
-(1)带参数的构造函数中的形参,其对应的实参在定义对象时给定。
-(2)用这种方法可以方便地实现对不同的对象进行不同的初始化。
用参数初始化表对数据成员初始化
- 不在函数体内对数据成员初始化,而是在函数首部实现。
Box::Box(int h, int w. int len):height(h), width(w), length(len) { }
构造函数的重载
- 在调用构造函数时不必给出实参的构造函数,称为默认构造函数(default constructor)或者缺省构造函数。
- 如果在建立对象时选用的是无参构造函数,应注意正确书写定义对象的语句。
Box box1 // 应该没有括号
- 尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行。
使用默认参数的构造函数
- 应该在声明构造函数时指定默认值,而不能只在定义构造函数时指定默认值。
- 在声明构造函数时,形参名可以省略,即写成:
Box(int = 10, int = 10, int = 10);
. - 一个类只能有一个默认构造函数。
Box();
Box(int = 10, int = 10, int = 10);
在建立对象时,如果写成Box box1;,编译系统无法识别。 - 在一个类中定义了全部是默认参数的构造函数后,不能再定义重载构造函数。
析构函数(Destructor)
- 不返回任何值,没有函数类型,没有函数参数。由于没有函数参数,因此不能被重载,一个类可以由多个构造函数,但是只能有一个析构函数。
调用构造函数和析构函数的顺序
- 先构造的后析构,后构造的先析构。
对象数组
- 编译系统只为每个对象元素的构造函数传递一个实参。
- 对象数组的初始化:在花括号中分别写出构造函数并指定实参。
- 在建立对象数组时,分别调用构造函数,对每个元素初始化。每一个元素的实参分别用括号包起来,对应构造函数的一组形参,不会混淆。
对象指针
指向对象的指针
- 一般形式:
类名 * 对象指针名
- 可以通过对象指针访问对象和对象的成员:
Time * pt; // 定义pt为指向Time类对象的指针变量
Time t1; // 定义t1为Time类对象
pt = &t1; // 将t1的起始地址赋给pt
* pt // pt所指向的对象,即t1
(* pt).hour // pt所指向的对象中的hour成员,即t1.hour
pt -> hour // pt所指向的对象中的hour成员,即t1.hour
(* pt).get_time() // 调用pt所指向的对象中的get_time函数,即t1.get_time
pt -> get_time() // 调用pt所指向的对象中的get_time函数,即t1.get_time
指向对象成员的指针
- 指向对象的指针:存放对象初始地址的指针变量
- 指向对象成员的指针:存放对象成员地址的指针变量
- 指向对象数据成员的指针:
数据类型名 * 指针变量名;
int * pt;
p1=&t1.hour;
cout << *pt << endl; // 输出ti.hour的值 - 指向对象成员函数的指针
1)指向普通函数的指针变量:数据类型名 (* 指针变量名)(参数表列);
void (* p) (); // p是指向void型函数的指针变量
p=fun; // 将fun函数的入口地址赋给指针变量p,p就指向了函数fun
(*p) (); 、//调用fun 函数
2)指向对象成员函数的指针:
数据类型名(类名:: * 指针变量名)(参数表列);
指针变量名 = &类名::成员函数名;
void (Time:: * p2) (); // 定义p2为指向Time类中公用成员函数的指针变量
p2=&Time:: get_time; // 把公用成员函数的入口地址赋值给一个指向公用成员函数的指针变量。
关于对象指针的使用方法。(P86)
#include<iostream>
using namespace std;
class Time
{
public:
Time( int, int, int);
int hour;
int minute;
int sec;
void get_time(); // 声明公有成员函数
};
Time::Time(int h, int m, int s) // 定义构造函数
{
hour = h;
minute = m;
sec = s;
}
void Time::get_time() // 定义公有函数
{ cout << hour << ":" << minute << ":" << sec << endl;}
int main()
{
Time t1(10, 13, 56); //定义Time类对象t1
int * p1 = &t1.hour;
cout << *p1 << endl;
t1.get_time();
Time *p2 = &t1;
p2 -> get_time();
void (Time::*p3)();
p3=&Time::get_time;
(t1.*p3)();
}
main函数中第8、9行可换成:
void(Time::*p3)()=&Time::get_time; //定义指针变量时指定其指向
- 成员函数不是存放在对象的空间中的,而是存放在对象外的空间中的。
零散记录
1.&
:地址运算符。
2.*
:运算符:间接值或解除引用运算符,应用于指针,可以得到该地址处存储的值。
int jumbo = 23;
int * pe = &jumbo;
则 jumbo = * pe 都是值23
& jumbo = pe 都是地址
3.error:非静态成员引用必须与特定对象相对。
4.error:使用switch的时候在case下边实例化对象的时候会提示“控制传输跳过的实例化”。、
将case下的语句加上"{}"即可。