一、类的定义
(1)格式:
class 类名
{
权限控制符:
成员;(成员变量\成员函数)
};
(2)权限控制符包括:
public:成员类内可以访问 类外可以访问、
protected:成员类内可以访问 类外不可以访问、子类可以访问父类的protected成员
private: 成员类内可以访问 类外不可以访问 子类不可以访问父类的private成员
(3)在类外实现成员函数,需在返回值类型之后、函数名之前加上所属类作用域即“类名::”
格式:返回值类型 类名::函数名 (参数列表){函数体}
二、对象的创建与使用
1、定义格式:类名 对象名;
2、对象的成员变量和成员函数的访问可以通过“ . ”运算符实现。
三、this指针
(1)成员变量和成员函数分开存储的
空对象占内存空间为:1
静态成员函数、静态成员变量、非静态成员函数都不属于类的对象上;只有非静态成员变量 属于类对象上,占用类对象存储空间
(2)this指针指向被调用的成员函数所属的对象
(3)this用途:1、解决名称冲突this->age=age;
2、返回对象本身return *this;
Person& PersonAddAge(Person p){
this->age=p.age;
return *this;}
注意:返回值类型是引用,如果是值Person,则发生拷贝,this为未进行加运算 的原对象
四、构造函数
1、自定义构造函数:完成对象的初始化
注意:(1)如果在类中提供了自定义构造函数,编译器便不再提供默认构造函数
(2)构造函数没有返回值,不用写void
(3)函数名与类名相同
(4)无返回值,有参数,可以重载
(5)调用默认构造函数时,不要加(),否则编译器会认为是一个函数声明
(6)编译器自动创建默认构造函数、析构函数、拷贝构造函数;一旦自定义有参构造函数,编译器将不再提供默认构造函数,拷贝构造函数依然提供;一旦自定义拷贝构造函数,编译器将不再提供默认构造函数。
2、自定义无参构造函数、自定义有参构造函数、通过“ :”运算符在构造函数后初始化成员变量
类::构造函数(参数列表):成员变量1(参数一),成员变量2(参数2),....,成员变量(参数n){ 构造函数体 }
#include<iostream>
#include<string>
using namespace std;
class Birth{
public:
Birth(){}//无参构造
Birth(int year, int month, int day);//有参构造
void show();
private:
int _year;
int _month;
int _day;
};
//通过“:”初始化
Birth::Birth(int year, int month, int day) :_year(year), _month(month), _day(day)
{
cout << "Brith类构造方法函数" << endl;
}
void Birth::show(){
cout << "出生日期" << _year << "-" << _month << "-" << _day << endl;
}
3、拷贝构造函数
(1)格式
构造函数名称(const 类名 & 对象名){ 函数体 }
(2)调用时机
a、使用一个已经创建好的对象来初始化一个新的对象
b、值传递的方式给函数参数传值
c、以值的方式返回局部对象
(3)深拷贝与浅拷贝
自己实现拷贝构造函数,解决浅拷贝带来的问题
注:Person成员变量:public:int _age;int *_height;
Person(const Person &p)
{
cout<<"Person 拷贝构造函数"<<endl;
_age=p._age;
//_height=p._height;编译器默认实现这行代码
//深拷贝操作
_height = new int(*p._height);
}
4、调用
(1)括号法
Birth b1;Birth b2(2012,10,2);Birth b3(b2);
(2)显示法
Birth b1;Birth b2=Birth(2012,10,2);Birth b3=Birth(b2)
(3)隐式转换法
Birth b3=b2;
五、类对象作为类成员
(1)格式:
class B { A a; ... }
(2)构造
B(参数列表)::成员变量1(参数1),成员变量2(参数2),... ,a(参数n-1,参数n){ }
B(参数列表)::a(参数n-1,参数n)
{成员变量1= 参数1; 成员变量2 = 参数2;....}
B(参数列表){成员变量1= 参数1; 成员变量2 = 参数2;a.成员变量=参数....}
(3)注意:
当其他类对象作为本类成员,构造是先构造成员变量类对象,再构造自身类对象
析构顺序与构造顺序相反
六、静态成员static、const修饰成员函数
静态成员函数只能访问静态成员变量
成员函数后加const后我们称这函数为常函数
常函数不可以修改成员属性
成员属性声明时加关键字mutable后,在常函数中依然可以修改
声明对象前加const称该对象为常对象
常对象只能调用常函数,因为普通成员函数可以修改成员属性
#include<iostream>
using namespace std;
class Person {
public:
int _A;
mutable int _B;
//this指针的本质 是指针常量 指针的指向是不可以修改的
//const Person * const this;
//在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
void showPerson() const
{
this-> _B = 100;
//this->_A = 100;
//this = NULL;this指针不可以修改指针的指向
}
};
void test() {
Person p;
}
int main(){
test();
return 0;
}
七、友元
(1)友元的目的就是让一个函数或类访问另外一个类中的私有成员
(2)友元的关键字friend
(3)友元三种实现:全局函数做友元、类做友元、成员函数做友元
全局函数做友元格式:
class 类名
{ friend 函数返回值类型 友元函数名(形参列表);
.....//其他成员
}
类做友元格式:
class B;
class A{};
class B{ friend class A; };声明A是B的友元类
成员函数做友元格式:
class B;
class A{ public:int func(); };
class B{ friend int A::func(); };声明类A的成员函数func()为友元函数
#include<iostream>
#include<math.h>
using namespace std;
class Point;
class Circle {
private:
const float PI = 3.14;
public:
float getArea(Point& p1, Point& p2);
};
class Point {
friend float Circle::getArea(Point& p1, Point& p2);
public:
Point(float x, float y);
~Point();
private:
float _x;
float _y;
};
Point::Point(float x = 0, float y = 0) :_x(x), _y(y) {
cout << "初始化坐标点" << endl;
}
Point::~Point() {}
float Circle::getArea(Point& p1, Point& p2) {
float x = abs(p1._x - p2._x);
float y = abs(p1._y - p2._y);
float len = sqrtf(x * x + y * y);
cout << "获取两个坐标点之间的距离是" << len << endl;
return len * len * PI;
}
int main() {
Point p1(5, 5);
Point p2(10, 10);
Circle circle;
float area = circle.getArea(p1, p2);
cout << "圆的面积是" << area << endl;
system("pause");
return 0;
}
八、运算符重载
(1)加法运算符重载格式:
返回值类型 operater运算符 (参数列表){ 函数体 。。。}
双目运算符重载后调用格式
左操作数.运算符重载函数名(右操作数)注a1+a2相当于a1.operater+(a2);
(2)左移运算符重载,
只能利用全局函数重载左移运算符,访问私有成员需要友元
格式:ostream& operator<<(ostream& 别名,const 类对象引用);
istream& operator>>(istream& 别名,类对象引用);
(3)递增运算符重载
单目运算符重载后调用格式
前置递增返回值是引用
后置递增返回值是值
#include<iostream>
using namespace std;
class MyInteger {
friend ostream& operator<<(ostream& out, MyInteger myint);
private:
int _Num;
public:
MyInteger() {
_Num = 0;
}
//前置运算符 返回引用为了一直对一个数据进行递增操作
MyInteger& operator++() {
_Num++;
return *this;
}
//后置运算符
MyInteger operator++(int) {
MyInteger temp = *this;
_Num++;
return temp;
}
};
ostream& operator<<(ostream& out, MyInteger myint) {
out << myint._Num;
return out;
}
void test01() {
MyInteger myint;
cout << ++(++myint) << endl;
cout << myint << endl;
}
void test02() {
MyInteger myint;
cout << myint++ << endl;
cout << myint << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
(4)赋值远算符重载
#include<iostream>
using namespace std;
class Person {
public:
Person(int age) {
_age = new int(age);
}
//重载赋值运算符
Person& operator=(Person& p)
{
if (_age != NULL) {
delete _age;
_age = NULL;
}
//提供深拷贝 解决浅拷贝重复释放的问题
_age = new int(*p._age);
//返回引用本身,可以进行重复赋值操作
return *this;
}
~Person() {
if (_age != NULL) {
delete _age;
_age = NULL;
}
}
int *_age;
};
void test01() {
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1;
cout << "p1的年龄:" << *p1._age << endl;
cout << "p2的年龄:" << *p2._age << endl;
cout << "p3的年龄:" << *p3._age << endl;
}
int main() {
test01();
return 0;
}
(5)关系远算符重载
bool operator运算符(参数列表){ 函数体 ....}
(6)仿函数(重载小括号)
#include<iostream>
using namespace std;
class MyAdd {
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
void test02() {
MyAdd add;
int ret = add(10, 10);
cout << "ret=" << ret << endl;
//匿名对象调用MyAdd()
cout << "MyAdd()(100,100)=" << MyAdd()(100, 100) << endl;
}
int main() {
test02();
return 0;
}