3.1 类和对象、this指针
this指针 :一个类可以产生很多对象,共享一套成员方法,this指针用来区分不同成员方法。
3.2 构造函数和析构函数
#include "iostream"
using namespace std;
class SeqStack {
public:
SeqStack(int size = 5) { //构造函数
cout << this <<"我是构造函数" <<endl;
_data = new int[size];
_top = -1;
_size = size;
}
~SeqStack(){ //析构函数
cout <<this << "我是析构函数" <<endl;
delete[] _data;
_data = nullptr;
}
// void init(int size = 5) {
// _data = new int[size];
// _top = -1;
// _size = size;
// }
// void release() {
// delete[] _data;
// _data = nullptr;
// }
void push(int x) {
if (_top == _size - 1) {
resize(); //栈满执行扩容操作
}
_data[++_top] = x;
}
void pop() {
if (_top == -1) {
return;
}
--_top;
}
bool empty() {
return _top == -1;
}
int top() {
return _data[_top];
}
private:
int *_data; //动态开辟数组,存储顺序栈的元素
int _top; //栈顶指针
int _size; //顺序栈的大小
void resize() {
int *new_data = new int[_size*2];
for (int i =0;i<_size;++i) {
new_data[i] = _data[i];
}
delete[] _data;
_data = new_data;
_size *= 2;
}
};
SeqStack s2;
int main() {
SeqStack *ps = new SeqStack(12); //先调用malloc(sizeof(SeqStack)),然后调用SeqStack()
ps->push(10);
ps->push(20);
ps -> pop();
cout << ps->top() << endl;
delete ps; //先调用~SeqStack(),然后调用free(ps)
SeqStack s;
//s.init(5);
for (int i = 0; i < 10; ++i) {
s.push(i);
}
while (!s.empty()) {
cout << s.top() << " ";
s.pop();
}
SeqStack s1(20);
//s.release();
return 0;
}
3.3 对象的深拷贝和浅拷贝
浅拷贝与深拷贝的区别:
浅拷贝:在拷贝的对象成员有占用外部资源时,两个指针同时指向同一块内存地址,析构函数在释放时会重复释放,后面释放的是野指针,导致程序崩溃。
深拷贝:会为拷贝的对象重新开辟一片内存空间,两个指针指向的是不同的地址。
3.4 拷贝构造函数的应用实践
#include "iostream"
using namespace std;
class Queue{
public:
//构造函数
Queue(int size=5){
_data = new int[size];
_front = _rear = 0;
_size = size;
}
Queue(const Queue &q) {
_data = new int[_size];
_front = q._front;
_rear = q._rear;
_size = q._size;
for (int i = _front;i!=_rear;i=(i+1)%_size) {
_data[i] = q._data[i];
}
}
Queue& operator=(const Queue &q){
if(this == &q) {
return *this;
}
delete[] _data;
_data = new int[_size];
_front = q._front;
_rear = q._rear;
_size = q._size;
for (int i = _front;i!=_rear;i=(i+1)%_size) {
_data[i] = q._data[i];
}
return *this;
}
//析构函数
~Queue() {
delete[] _data;
_data = nullptr;
}
bool empty() {
return _front == _rear;
}
bool full() {
return (_rear+1)%_size == _front;
}
void push(int x) {
if(full()) {
resize();
}
_data[_rear] = x;
_rear = (_rear+1)%_size;
}
void pop() {
if(empty()) {
return;
}
_front = (_front+1)%_size;
}
int front() {
return _data[_front];
}
private:
int *_data;
int _front;
int _rear;
int _size;
void resize(){
int num = 0;
int *_new_data = new int[_size*2];
for(int i=_front;i!=_rear;i=(i+1)%_size) {
_new_data[num++] = _data[i];
}
delete[] _data;
_data = _new_data;
_front = 0;
_rear = num;
_size *=2;
}
};
int main() {
Queue q1;
for (int i=0;i<15;++i) {
q1.push(rand()%100);
}
while(!q1.empty()) {
cout << q1.front() << " ";
q1.pop();
}
Queue q2 = q1;
return 0;
}
3.5 构造函数的初始化列表
#include "iostream"
using namespace std;
class Test {
public:
Test(int data = 10):mb(data),ma(mb) {
}
void show() {
cout << ma << " " << mb << endl;
}
private:
//成员变量的初始化和他们定义的顺序有关,与构造函数的初始化列表顺序无关
int ma;
int mb;
};
int main() {
Test t;
t.show();
return 0;
}
3.6 类的各种成员方法及其区别
-
普通的成员方法:=>编译器会添加一个this指针形参变量。
1.属于类的作用域;2.调用该方法时,需要依赖一个对象(常量对象无法调用);3.可以任意访问对象的私有成员。
-
static静态成员方法:=>不会生成this指针。
1.属于类的作用域;2.用类名作用域来调用该方法;3.可以任意访问不依赖对象的的成员,如static静态成员变量。
-
const常成员方法:=> const Student *this
1.属于类的作用域;2.调用依赖一个对象,普通对象或常量对象都可以调用;3.可以任意访问对象的私有成员,但只能读,而不能写。
#include <string.h>
#include "iostream"
using namespace std;
class Student {
public:
Student(const char *name,int age,char sex,float height,char *address)
:_age(age),
_sex(sex),
_height(height)
{
strcpy(_name,name);
strcpy(_address,address);
_count++;
}
void show() {
cout << "姓名:" << _name << endl;
cout << "年龄:" << _age << endl;
cout << "性别:" << _sex << endl;
cout << "身高:" << _height << endl;
cout << "家庭地址:" << _address << endl;
}
void show()const { //调用方法时只有读操作,没有写操作时,一律写成const常成员方法。
cout << "姓名:" << _name << endl;
cout << "年龄:" << _age << endl;
cout << "性别:" << _sex << endl;
cout << "身高:" << _height << endl;
cout << "家庭地址:" << _address << endl;
} //普通成员方法,生成this指针
static void showStudentcount() {
cout << "总共学生数量为:" << _count << endl; //打印所有学生共享的信息
} //静态成员方法,不生成this指针
private:
char _name[20];
int _age;
char _sex;
float _height;
char _address[20];
static int _count; //不属于对象,而属于类级别的,用来记录所有产生的新对象的数量
};
int Student::_count = 0; //static成员变量要在类外进行定义并初始化
int main () {
Student s1("lmh",24,'m',178.5,"陕西省咸阳市兴平市xx村");
Student s2("xy",23,'m',176.0,"重庆市开州区");
Student s3("zjw",23,'m',176.5,"陕西省渭南市");
s1.show();
s2.show();
s3.show();
Student::showStudentcount();
const Student s4("zjw1",23,'m',176.5,"陕西省渭南市");
s4.show();
return 0;
}
3.7 指向类成员的指针
指向类成员方法的指针、指向类成员变量的指针,必须加上相应的对象才能调用。
#include "iostream"
using namespace std;
class Test {
public:
void func1() {
cout << "func1" << endl;
}
int ma;
static int mb;
};
int Test::mb;
int main() {
Test t1;
void(Test::*pfunc)() = &Test::func1;
(t1.*pfunc)(); //指针调用类成员方法
int Test::*p = &Test::ma;
Test t;
t.*p = 20; //指针调用类成员变量
cout << t.*p << endl;
int *p1 = &Test::mb;
*p1 = 30;
cout << *p1<<endl;
return 0;
}