目录
一.C语言和C++的区别
二.类的引入
三.类的定义
1.类的定义
2.类的成员方法的两种定义方式:
3.类的成员变量的定义
四.类的访问限定符及封装
1.访问限定符
五.面向对象的三大特征
1.面向对象的三大特征分别是什么
2.封装
六.类的作用域
七.创建类对象
1.类对象的实例化
2.类的大小
3.匿名对象
八.this指针
1.什么是this指针
2.关于this指针的两个问题。
九.C++类中的默认成员函数
1.类的6个默认成员函数
2.构造函数 (完成创建对象时的初始化工作) 是特殊的成员函数 构造函数可以私有化
a.特性:
b.类的构造函数的调用
3.析构函数(完成对象销毁时的清理工作) 先定义的后析构,后定义的先析构
a.特征:
b.不用显示调用析构函数的情况:
c.类对象的析构问题
4.拷贝构造函数(特殊的构造函数)是构造函数的重载。
a.特征:
5.运算符的重载
什么是运算符的重载
赋值运算符的重载
a. 赋值运算符重载格式
b. 赋值运算符只能重载成类的成员函数不能重载成全局函数
c. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。
注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。
前置++和后置++运算符的重载
a.前置++:
b.后置++:
流定向运算符的重载
6.取地址及const取地址操作符重载
十.const成员
十一.初始化列表
1.什么是初始化列表
2.为什么有了构造函数还需要初始化列表:
【注意】
十二.explicit关键字
十三.Static成员
1.概念
2.特性
十四.友元
1.什么是友元
2.友元函数
3.友元类
十五.内部类
1.概念:
2.特性:
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
class className
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分
// 我们看看这个函数,是不是很僵硬?classDate
{
public:
void Init(int year)
{
// 这里的year到底是成员变量,还是函数形参?
year = year;
}
private:
int year;
};
// 所以一般都建议这样
class Date
{
public:
void Init(int year)
{
_year = year;
}
private:
int _year;
};
// 或者这样
class Date
{
public:
void Init(int year)
{
mYear = year;
}
private:
int mYear;
};
// 其他方式也可以的,主要看公司要求。一般都是加个前缀或者后缀标识区分就行。
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
class Person
{
public:
void PrintPersonInfo();
private:
char _name[20];
char _gender[3];
int _age;
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
cout << _name << " "<< _gender << " " << _age << endl;
}
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout <<_year<< "-" <<_month << "-"<< _day <
对于上面的代码的d1和d2两个对象在访问成员方法时,既然成员方法都在一个共享空间中,那么为什么两个对象的输出结果不同呢?
原因就是有 this指针的存在。
this指针是非静态成员函数默认定义的一个行参 Date&const this; 因为是const类型所以在函数中不可以改变this指针变量的内容。既然是一个形参那么出函数作用时就会销毁。this指针不可以在函数的形参和实参显示传递。
a.this指针是存放在栈空间的。
b.this可以为空吗?
可以为空
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void Print()
{
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void PrintA()
{
cout<<_a<PrintA();
return 0;
}
#include
using namespace std;
class Date
{
public:
Date(int year = 2023,int month = 12, int day = 31)
{
_year = year ;
_month = month;
_day = day ;
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1;
Date d2(2023, 12, 3);
Date d3();
return 0;
}
先看下面的代码:
#include
using namespace std;
class Date
{
public:
Date(int year = 2023,int month = 12, int day = 31)
{
_year = year ;
_month = month;
_day = day ;
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1;
Date d2(2023, 12, 3);
cout << d2;
return 0;
}
#include
using namespace std;
class Date
{
friend ostream& operator<< (ostream& cout, const Date& d);
public:
Date(int year = 2023,int month = 12, int day = 31)
{
_year = year ;
_month = month;
_day = day ;
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1;
Date d2(2023, 12, 3);
cout << d1;
return 0;
}
ostream& operator<< (ostream& cout, const Date& d)
{
cout << d._year << " " << d._month << " " << d._day << endl;
return cout;
}
此时一定要使用ostream&因为ostream类有防止开拷贝的操作。
class Date
{
public :
Date* operator&()
{
return this ;
}
const Date* operator&()const
{
return this ;
}
private :
int _year ; // 年
int _month ; // 月
int _day ; // 日
};
class A
{
public:
A() { ++_scount; }
A(const A& t) { ++_scount; }
~A() { --_scount; }
static int GetACount() { return _scount; }
private:
static int _scount;
};
int A::_scount = 0;
void TestA()
{
cout << A::GetACount() << endl;
A a1, a2;
A a3(a1);
cout << A::GetACount() << endl;
}
class Date
{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用
// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧
ostream& operator<<(ostream& _cout)
{
_cout << _year << "-" << _month << "-" << _day << endl;
return _cout;
}
private:
int _year;
int _month;
int _day;
};
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
friend istream& operator>>(istream& _cin, Date& d);
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
_cin >> d._year;
_cin >> d._month;
_cin >> d._day;
return _cin;
}
int main()
{
Date d;
cin >> d;
cout << d << endl;
return 0;
}
class Time
{
friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成
员变量
public:
Time(int hour = 0, int minute = 0, int second = 0)
: _hour(hour)
, _minute(minute)
, _second(second)
{}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
void SetTimeOfDate(int hour, int minute, int second)
{
// 直接访问时间类私有的成员变量
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
class A
{
private:
static int k;
int h;
public:
class B // B天生就是A的友元
{
public:
void foo(const A& a)
{
cout << k << endl;//OK
cout << a.h << endl;//OK
}
};
};
int A::k = 1;
int main()
{
A::B b;
b.foo(A());
return 0;
}