学习没有捷径,但考试有捷径
临近考试,虽然之前对一些概念搞清楚了,但时日一长,很多又模糊了。因此利用整理成章,将知识重拾。
考试的范围如下:
- 常量(const、符号、字符串常量、立即数)
- 引用和指针
- 类的封装和隐藏(静态成员、友元函数)
- 类的初始化(初始化方式和顺序)
- 类的继承(继承方式、构函列表、多继承)
- 类的多态性(函数重载、运算符重载、虚函数、虚函数表)
- 类的作用域概念
概念
类
用户定义的新的复杂数据类型
将不同类型的数据及数据的操作(函数)封装起来
实现数据封装和信息隐藏
对象
具体的实例变量
可以有对象数组,指针及引用
知识点
- 类体内不可对数据成员进行初始化
- 如果另一个类的对象作为一个类的成员,则那个类的定义必须在这个类定义之前存在,但类的成员函数中引用或指针可以先声明,其后定义。
class B;
class A
{
private:
int a;
public:
B* h;
……
具体定义见复制构造函数部分
A m;
B n(2);
n.getValue();
m.h = &n;
m.h->change(5) ;
n.getValue();
- 成员函数在类体内定义,内联函数(不必定,编译器决定);在类体外加inline关键词处理为内联函数
构造函数
- 不指定返回类型,隐含有返回值
- 可以重载
- 创建对象时自动调用构造函数
- 只要用户定义一个构造函数,系统不提供默认构函
- 默认构函不进行初始化,但静态变量为零
static Point p;
初始化列表
Date:: Date(int y, int m, int d): year(y), month(m), day(d)
{
cout<<"Constructor of Date with 3 parameters."<<endl;
}
- 先执行初始化列表,再执行构造函数体
- 执行顺序取决于类成员声明顺序
析构函数
- 不指定返回类型,隐含有返回值
- 没有参数,不可重载
- 撤销对象时,系统自动调用
复制构造函数
- 默认复制构造函数,只做位拷贝
- 因此没有申请新空间,当析构函数调用时,两次delete,非法
在验证类的函数中引用是否可以先声明,后定义时,使用如下代码。
class B
{
public:
B()
{
cout << "constructor of B" << endl;
b = 0;
cout << "set b to 0" << endl;
}
B(int b) :b(b)
{
cout << "constructor of B" << endl;
cout << "set b to " << b << endl;
}
~B()
{
cout << "destructor of B" << endl;
}
void change(int t)
{
b = t;
cout << "change b to " << b << endl;
}
int getValue()
{
cout << "b is " << b << endl;
return b;
}
private:
int b;
};
class A
{
private:
int a;
public:
A(int a) :a(a)
{
cout << "constructor of A"<<endl;
cout << "set a to " <<a<< endl;
}
A()
{
cout << "constructor of A" << endl;
a = 0;
cout << "set a to 0" << endl;
}
~A()
{
cout << "destructor of A" << endl;
}
void process(B t)
{
cout << "process B from A" << endl;
t.change(a);
}
void print()
{
cout << "a= " << a<<endl;
}
};
int main(void)
{
A m;
B n(3);
m.process(n);
return 0;
}
结果如下:
显示的结果为调用B的析构函数比构造函数多一次,使用复制构造函数
加入自定义复制构造函数进行显示:
B(const B& t)
{
b = t.b;
cout << "copy constructor of B" << endl;
}
结果为:
则调用复制构函显然有另一种方式,即用已有的对象初始化另一个对象:
B b1(2);
B b2(b1);
还有一种则是对象做为函数返回值
B create(int s)
{
B temp(s);
return temp;
}
int main(void)
{
B b = create(3);
return 0;
}