目录
3.0 只有当类中没有任何构造函数时,系统才会生成一个无参的构造函数。
3.1 默认拷贝构造函数对数据成员作浅拷贝,一旦涉及指针、堆空间申请等操作,或需手动实现深拷贝。
1. 面对对象基本概念
1.0 对象的两个要素是属性和方法。将相同或相近的对象抽象出来就形成了类。
1.1 面向过程与面向对象的区别
面向过程是分析问题解决的步骤,明确每个步骤的输入和输出以及个流程,是一种结构化的自上而下的程序设计方法。
面对对象是把构成问题的事务分解成对象,以数据为核心,以构建类为主要工作的自上而下程序设计方法。
1.2 面对对象的基本特征
首先类是抽象的。
封装性:把自己的属性和方法隐藏起来。
继承性:代码复用。
多态性:多态是指不同对象对于同样的消息做出不同的响应。程序中通过运行时绑定实现多态。例如,一个父类指针只有在运行时菜知道自己实际绑定的对象类型,程序可以将子类对象地址赋值给父类指针,在调用方法时,根据具体的对象类型执行相应子类中的方法。
2. 类的声名
2.0 类和结构体的区别
类class中默认访问权限时private,结构体struct时public。
2.1 类中静态数据成员与静态成员函数
示例代码:
class Trade
{
private:
double _amount;
static double _fee; //#1
public:
Trade(double amount) { this->_amount = amount; }
double getDirty() { return _amount; }
static double getFee() { return _fee; } //#3
double getClean() { return _amount *(1 - _fee / 100); } //#4
};
double Trade::_fee = 0.08; //#2int main()
{
double x;
x = Trade::getFee(); //#方式1Trade tr(10);
x = tr.getFee(); //#方式2Trade * tp = new Trade(10);
x = tp->getFee(); //#方式3cout << x << endl;
}
代码中使用static修饰符声名了一个静态数据成员:
static double _fee; //#1
静态数据成员属于整个类,不属于某一个对象,静态数据只有唯一的一份拷贝,所有对象共享静态数据成员。没有使用static修饰的数据成员在每个对象中都有自己的一份。
静态数据成员必须在类内部声名,在类外初始化。
double Trade::_fee = 0.08; //#2
程序中定义的静态成员函数:
static double getFee() { return _fee; } //#3
静态成员函数也同样属于类本身,不属于某一个对象。静态成员函数和普通函数最大的区别在于,静态成员函数没有this指针。普通函数调用时,会将对象的地址隐式的作为第一参数,也就this指针。既然静态成员函数中没有this指针,那么在静态函数中也就不能访问非静态成员了,因为非静态成员都是通过this指针访问的。换句话说:在静态函数中只能访问静态成员,包括静态数据成员和静态成员函数。
静态成员函数的调用有如上的三种方式,但实际上方式2和方式3会隐式转换为方式1的形式。
2.2 const 修饰符在类中的用法
示例代码:
class Test
{
private:
const int _num; //#1
public:
Test(int n):_num(n) { } //#2
int getNum() const { return _num; } //#3
};int main()
{
int x = 10;
Test t(x);
x = t.getNum();
cout << x << endl;
}
类中声名了唯一的一个const修饰的变量_num,需要注意的是,必须通过构造函数的初始化列表初始化const成员。初始化后的值不能修改。不能在构造函数体内初始化,因为初始化不同于赋值,构造函数中的赋值语句相当于改变了初始化列表在初始化时的默认值,这与const修饰符的作用相悖。
Test(int n):_num(n) { } //#2
在成员函数后加上const修饰符表示不能在函数中修改类的数据成员。
int getNum() const { return _num; } //#3
2.3 友元函数和有元类
友元函数不是类中的成员函数,而是类外部的函数。友元函数能够访问类的非公有成员。
class Test
{
private:
int _num;
public:
Test(int num):_num(num){}
friend int getNum(const Test &t);
};
int getNum(const Test &t)
{
return t._num;
}int main()
{
Test t(10);
cout << getNum(t) << endl;
}
有缘类与友元函数类似,可以将一个类A声名为类一个类B的友元,这样类B就可以访问类A的非公有成元。唯一需要注意的是友元关系不能继承。
class A
{
private:
int _num;
public:
A(int num):_num(num){}
friend class B;
};class B
{
public:
int get