封装:
将东西包裹起来,使外界无法知道,只能通过某些特定的方式才能访问。其目的是增强安全性和简化编程,使用方无需知道其具体实现,只能通过外部接口以及特定的权限来使用其成员。
C++中的类就是把属性和方法进行封装,同时对外部的访问通过访问限定符进行限制。而类是一种抽象的概念的数据类型,就像设计图一样,是对设计物抽象的描述,而真实存在的是物品。对于C++而言,对象是类的存在形式,占用内存空间。
类将数据和函数通过访问限定符进行访问限制:
public: 任意位置都可以访问
protected: 子类,本类类中允许访问
private: 本类类中访问
using namespace std;
/* 抽象一个圆类,并对圆的属性和方法进行封装 */
class Circle
{
//私有成员,只允许本类访问
private:
double r; /* 圆类的半径属性 ,*/
//共有成员,任何位置都可以访问
public:
void setR(double r) /* 设置圆的半径 */
{
this->r = r;
}
double getR() /* 获取圆的半径 */
{
return this->r;
}
};
对象的生成和销毁:
生成:1、对象开辟内存空间;2、对象内存初始化(调用构造函数)
销毁:1、释放对象所占其他资源(调用析构函数);2、释放对象所占内存空间
为了方便对象的使用,C++定义了六个默认函数(若程序不定义或不调用,编译器自动定义或调用的函数)
1、默认构造函数(初始化对象的内存空间(不包括堆区成员),类指针和类引用不会生成对象,也就不会调用构造函数)
public:
Test()
{
}
特点:函数名与类名相同,没有返回值;可重载,不能手动调用(类的成员函数依赖对象调用),按照定义顺序构造。
class Test
{
public:
Test(int a, int b)
{
std::cout << this << "Test:: Test(int,int)" << std::endl;
ma = a;
mb = b;
}
Test(int a)
{
std::cout << this << "Test:: Test(int)" << std::endl;
ma = a;
}
Test()
{
std::cout << this << "Test:: Test()" << std::endl;
}
Test(const Test& rhs)
{
std::cout << this << "Test:: Test(const Test&)" << std::endl;
ma = rhs.ma;
mb = rhs.mb;
}
private:
int ma;
int mb;
};
2、默认析构函数(释放对象所占的其他资源,若有堆区成员,应提供适当的析构函数)
public:
~Test()
{
}
特点:函数名为"~"+类名,没有返回值;不可重载,可以手动调用(调用时退化成普通的成员方法),先构造后析构
3、默认拷贝构造函数(已存在的对象来生成一的相同类型的新对象,如果涉及指针注意,该拷贝为浅拷贝)
特点:函数名为类名,只有一个形参(未初始化的对象的引用),形参时类对象的引用,防止递归构造形参对象。
调用拷贝构造函数的情况:
1) 一个对象作为函数参数,以值传递的方式传入函数体;
2) 一个对象作为函数返回值,以值传递的方式从函数返回;
3) 一个对象用于给另外一个对象进行初始化(常称为赋值初始化);
1)、2)情况编译器会隐式生成临时对象(常量),3)情况由赋值和构造函数共同完成
class Test
{
public:
Test(int a, int b)
{
std::cout << this << "Test:: Test(int,int)" << std::endl;
ma = a;
mb = b;
}
Test(int a)
{
std::cout << this << "Test:: Test(int)" << std::endl;
ma = a;
}
Test()
{
std::cout << this << "Test:: Test()" << std::endl;
}
Test(const Test& rhs)
{
std::cout << this << "Test:: Test(const Test&)" << std::endl;
ma = rhs.ma;
mb = rhs.mb;
}
Test& operator=(const Test& rhs)
{
std::cout << this << "Test::operator = (const Test&)" << std::endl;
if (this != &rhs)
{
ma = rhs.ma;
mb = rhs.mb;
}
return *this;
}
~Test()
{
std::cout << this << "Test::~Test()" << std::endl;
}
private:
int ma;
int mb;
};
int main()
{
Test test7 = 10;//10编译器会匹配到参数类表为(int)的构造函数,隐式生成一个临时对象(常量),如果如果临时对象生成的目的是为了生成新对象,以生成临时对象的方式来生成新对象
Test test8 = Test(10);
//Test(10)显示调用构造函数,生成自定义类型临时对象(变量),如果如果临时对象生成的目的是为了生成新对象,以生成临时对象的方式来生成新对象
}
4.、默认赋值运算符的重载函数(已存在的对象赋值给相同类型的已存在对象,如果涉及指针注意存在内存泄漏)
特点:若为自赋值返回this指针;原内容丢弃,新内容覆盖(存在指针时,指针的值修改但原资源没有释放)
//返回类型为引用,避免调用构造函数和析构函数,减少栈争的开辟;参数为常引用,引用,防止重复调用构造函数导致栈争溢出;const,防止修改形参,考虑形参为隐式生成的对象(常量)
Test& operator=(const Test& rhs)
{
std::cout << this << "Test::operator = (const Test&)" << std::endl;
if (this != &rhs)
{
ma = rhs.ma;
mb = rhs.mb;
}
return *this;
}
5、默认取地址操作符的重载函数(一般对象的取地址函数返回该对象的地址)
class Base
{
public:
Base* operator&()
{
return this;
}
};
6、默认const修饰的取地址操作符的重载函数(常对象的取地址函数返回该对象的地址)
class Base
{
public:
const Base* operator&() const
{
return this;
}
};