指针指向类成员使用
代码:
#include<iostream>
using namespace std;
class Test
{
public:
void func() { cout << "call Test::func" << endl; }
static void static_func();
int ma;
static int mb; //不依赖对象
};
void Test::static_func() { cout << "Test::static_func " << endl; }
int Test::mb;
int main()
{
Test t1;
Test* t2 = new Test();
//int a= 10; int *p =&a; *p = 30;
//无法从"int Test::* 转换为 int *;
int Test::* p = &Test::ma;
//*p = 20;//错误
t1.*p = 20;
cout << "t1.ma = " << t1.ma << endl; //通过ma来看
t2->*p = 30;
cout << "t2-->ma = " << t2->ma << endl; //通过ma来看
int* p1 = &Test::mb;
*p1 = 40;
cout << Test::mb << endl;
//指向成员方法的指针
//无法转换 "初始化": 无法从"void (__cdecl Test::* )(void)"转换为"void (__cdecl *)(void)"
void(Test:: * func)() = &Test::func;
(t1.*func)();
(t2->*func)(); //普通成员函数依赖对象
//定义一个函数指针指向类的静态成员函数
void(*pfunc)() = &Test::static_func;
(*pfunc)();
delete t2;
return 0;
}
总结:针对类成员普通的指针需要指定对象
2、深浅拷贝
#include<iostream>
#include<string>
using namespace std;
class People
{
public:
People(const char* _name) : name(new char[strlen(_name) + 1])
{
strcpy_s(name, strlen(_name) + 1, _name);
}
People(const People& other) :name(new char[strlen(other.name) + 1]) //开辟控件赋值的是深拷贝
{
strcpy_s(name, strlen(other.name) + 1, other.name);
}
//深拷贝
People& operator =(const People& other)
{
name = new char[strlen(other.name) + 1];
strcpy_s(name, strlen(other.name) + 1, other.name);
}
~People()
{
delete[] name;
cout << "析构函数" << typeid(*this).name() << endl;
}
void print()
{
cout << name << endl;
}
private:
char* name;
};
int main()
{
People a("shabi");
People b(a);
People c = b;
c.print();
b.print();
a.print();
return 0;
}
效果如下:
3、构造和析构函数
#include<iostream>
using namespace std;
#include<time.h>
//构造函数和析构函数的讲解
class SeqStack
{
public:
/*void init(int size = 10)
{
_stack = new int[size];
_top = -1;
_size = size;
}*/
SeqStack(int size = 10) //可以重载,多个参数
{
_stack = new int[size];
_top = -1;
_size = size;
}
/*void release()
{
delete[] _stack;
_stack = nullptr;
}*/
~SeqStack()
{
delete[] _stack;
_stack = nullptr;
cout << "析构函数" << endl;
}
void push(int val)
{
if (full())
{
resize();
}
_stack[++_top] = val;
}
void pop()
{
if (empty())
{
return;
}
--_top;
}
int top()
{
return _stack[_top];
}
bool empty()
{
if (_top == -1)return true;
return false;
}
bool full() { return _top == _size - 1; }
private:
int* _stack;
int _size;//存储顺序栈的元素
int _top; //指向栈顶的位置
void resize()
{
int* tmp = new int[_size * 2];
for (int i = 0; i < _size; i++)
{
tmp[i] = _stack[i];
//memset(tmp,_stack,sizeof(int)*_size);realloc 内存的拷贝
}
delete[] _stack;
_stack = tmp;
tmp = nullptr;
_size *= 2;
}
};
int main()
{
SeqStack s;
for (int i = 0; i < 15; i++)
{
s.push(rand() % 100);
}
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
//s.release();//释放成员变量占用的外部堆内存
return 0;
}
效果如下:
4、构造函数的初始化列表
#include<iostream>
using namespace std;
#include<string>
/*
构造函数的初始化列表
*/
//日期类
class CDate
{
public:
CDate(int y, int m, int d) :_year(y), _month(m), _day(d) //自定义之后不会再产生默认的构造函数了
{
}
void show()
{
cout << "_year " << _year << endl;
cout << " _month" << _month << endl;
cout << "_day" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
class CGoods
{
public:
CGoods(const char* n, int a, double p, int y, int m, int d) :_date(y, m, d) //初始化的列表功能
{
strcpy_s(_name, strlen(n) + 1, n);
_amount = a;
_price = p;
}
void show()
{
cout << "name : " << _name << endl;
cout << "amount: " << _amount << endl;
cout << "price: " << _price << endl;
}
CDate test()
{
return _date;
}
private:
char _name[20];
int _amount;
double _price; //初始化顺序的时候,先name按照先后哈
/*
Test(int data = 10):mb(data),ma(mb);
private:
int ma;
int mb;先初始化ma然后是mb
*/
CDate _date; //成员对象 没有合适的默认构造函数 说明写了之后,默认的就没了
};
int main()
{
CGoods c("张三", 12, 12, 1, 1, 1);
c.show();
c.test().show();
return 0;
}
效果展示:
5、掌握类的各种成员方法以及区别
#include<iostream>
using namespace std;
#include<string>
/*
构造函数的初始化列表
*/
//日期类
class CDate
{
public:
CDate(int y, int m, int d) :_year(y), _month(m), _day(d) //自定义之后不会再产生默认的构造函数了
{
}
void show()
{
cout << "_year " << _year << endl;
cout << " _month" << _month << endl;
cout << "_day" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
class CGoods
{
public:
CGoods(const char* n, int a, double p, int y, int m, int d) :_date(y, m, d) //初始化的列表功能
{
strcpy_s(_name, strlen(n) + 1, n);
_amount = a;
_price = p;
goods_numbr++;
}
void show() const //常用方法
{
cout << "name : " << _name << endl;
cout << "amount: " << _amount << endl;
cout << "price: " << _price << endl;
}
CDate test()
{
return _date;
}
int get_number()
{
cout << "商品的总数量是: "<<goods_numbr << endl;
//cout<<name;这种错的,不能访普通成员的变量
return 1;
}
private:
char _name[20];
int _amount;
double _price; //初始化顺序的时候,先name按照先后哈
/*
Test(int data = 10):mb(data),ma(mb);
private:
int ma;
int mb;先初始化ma然后是mb
*/
CDate _date; //成员对象 没有合适的默认构造函数 说明写了之后,默认的就没了
//记录商品的成员变量数量
static int goods_numbr; //不属于对象属于类级别
};
int CGoods::goods_numbr = 0;
int main()
{
CGoods c("商品1", 12, 12, 1, 1, 1);
CGoods c1("商品2", 12, 12, 1, 1, 1);
CGoods c2("商品3", 12, 12, 1, 1, 1);
CGoods c3("商品4", 12, 12, 1, 1, 1);
c.show();
c.test().show();
c.get_number();
//统计商品的总数量
return 0;
}
/*
总结:
static静态成员方法
1、属于类的作用域
2、用类名作用域来调用方法
*/
6、类和对象、this指针
C++:OOP对象 OOP编程 this指针
C++:实体的抽象类型
四大特性: 抽象,封装,继承,多态
三种:公有私有以及保护 ,属性一般私有,提供公有的方法访问属性
7、实际运用
#include<iostream>
#include<string>
using namespace std;
//类和对象代码实践应用
class String
{
public:
String(const char* str = nullptr)
{
if (str != nullptr)
{
m_data = new char[strlen(str) + 1];
strcpy_s(this->m_data, strlen(str) + 1, str);
}
else
{
m_data = nullptr;
}
}
String(const String& other)
{
if (this != &other)
{
m_data = new char[strlen(other.m_data) + 1];
strcpy_s(m_data, strlen(other.m_data) + 1, other.m_data);
}
else
{
m_data = new char[1];
*m_data = '\0';
}
}
~String(void)//析构函数
{
delete[]m_data;
}
String& operator =(const String& other)
{
if (this == &other)
{
return *this;
}
delete[] m_data;
m_data = new char[strlen(other.m_data) + 1];
strcpy_s(m_data, strlen(other.m_data) + 1, other.m_data);
return *this;
}
private:
char* m_data;
};
int main()
{
String str1;
String str2("hello");
String str3(str2);
String str4 = str3 = str2;//调用赋值重载函数
}
//循环队列 memcpy realloc 不太合适
#include<iostream>
#include<time.h>
using namespace std;
class Queue
{
public:
Queue(int size = 5)
{
_queue = new int[size];
_front = _rear = 0;
_size = size;
}
//Queue(const Queue&) = delete;
//Queue& operator=(const Queue&) = delete;
Queue(const Queue& src)
{
_size = src._size;
_front = src._front;
_rear = src._rear;
_queue = new int[_size];
for (int i = _front; i != _rear; i++)
{
_queue[i] = src._queue[i];
}
}
Queue& operator = (const Queue& src)
{
if (this == &src)return *this;
_size = src._size;
_front = src._front;
_rear = src._rear;
_queue = new int[_size];
for (int i = _front; i != _rear; i++)
{
_queue[i] = src._queue[i];
}
return *this;
}
~Queue()
{
delete[] _queue;
_queue = nullptr;
}
void push(int val) //入队操作
{
if (full())
{
resize();
}
_queue[_rear] = val;
_rear = (_rear + 1) % _size;
}
void pop()
{
if (empty())
{
return;
}
_front = (_front + 1) % _size;
}
int front()
{
return _queue[_front];
}
bool full() { return (_rear + 1) % _size == _front; }
bool empty() { return _front == _rear; }
private:
int* _queue;
int _front;
int _rear;
int _size;
void resize()
{
int* ptmp = new int[2 * _size];
int index = 0;
for (int i = _front; i != _rear; i = (i + 1) % _size)
{
ptmp[index++] = _queue[i];
}
delete[]_queue;
_queue = ptmp;
_front = 0;
_rear = index;
_size *= 2;
}
};
int main()
{
Queue queue;
for (int i = 0; i < 20; i++)
{
queue.push(rand() % 100);
}
Queue queue1 = queue;//删掉了拷贝构造就不行了
while (!queue1.empty())
{
cout << queue1.front() << " ";
queue1.pop();
}
}