类和对象几个常见的知识
类和对象几个常见的知识
C++和C语言实现stack的区别
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
typedef struct stack
{
DataType* data;
int capacity;
int size;
}Stack;
void StackInit(Stack* ps)
{
ps->data = (DataType*)malloc(sizeof(DataType) * 10);
if (ps->data == NULL)
{
perror("malloc:");
exit(-1);
}
ps->capacity = 10;
ps->size = 0;
}
void StackCheck(Stack* ps)
{
if (ps->capacity == ps->size)
{
//扩容
DataType* tmp = (DataType*)realloc(ps->data, sizeof(DataType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc:");
exit(-1);
}
ps->capacity *= 2;
ps->data = tmp;
}
}
void Stackpush(Stack* ps,DataType x)
{
StackCheck(ps);
assert(ps);
ps->data[ps->size++] = x;
}
int main()
{
Stack sl;
StackInit(&sl);
Stackpush(&sl, 1);
}
typedef int DataType;
class Stack
{
public:
void Init()
{
_array = (DataType*)malloc(sizeof(DataType) * 10);
_capacity = 10;
_size = 0;
}
void push(DataType x)
{
_array[_size++] = x;
}
private:
DataType *_array;
int _capacity;
int _size;
};
int main()
{
Stack sl;
sl.Init();
sl.push(1);
在C语言中看到struct定义数据,操作的方法不能放在结构体中,言外之意就是数据和操作数据的方式是分开的
C语言有下面的一些共性
- 每个函数都有Stack*
- 必须对第一个参数检测,不然可能成为NULL
- 函数都是通过Stack*来操作栈的
- 传递参数时必须传递结构体变量的地址
在C++中操作数据的方法和数据是完美结合的,通过访问权限控制那些操作数据的方式在类外被调用,简称封装,在使用的时候就好比使用自己的成员一样,符合人们对事物的认知,并且每个方法不用传递Stack的参数了,编译器在编译之后参数会自动还原,简称C++中Stack参数编译器来维护,C语言需要用户来维护
类的6个默认构造函数
1->初始化和清理->构造函数主要完成初始化->析构函数主要完成函数的清理
2->拷贝复制->拷贝构造是使用同类对象初始创建对象->赋值重载主要是把一个对象赋值给另外一个对象
3->取地址重载->主要是普通对象和const对象取地址,这两个很少会自己实现
对于下面代码块
class Date
{
public:
void Init(int year, int month, int day)
{
比特就业课
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Init(2022, 7, 5);
d1.Print();
Date d2;
d2.Init(2022, 7, 6);
d2.Print();
return 0;
}
构造函数是一个特殊的成员函数,名字和类名相同,创建类类型的对象时由编译器自动调用,保证每一个成员有一个合适的初始值,并且在类对象的生命周期里面只调用一次
注意:构造函数是一个特殊的成员函数,他的名字是构造函数,但并不是创建函数,主要是对函数的初始化
主要特征:
- 函数名和类名相同,没有返回值
- 对象实例化时候编译器自动调用构造函数
- 构造函数可以重载
class Date
{
public:
// 1.无参构造函数
Date()
{}
// 2.带参构造函数
Date(int year, int month, int day)
{
_year = year;
比特就业课
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
void TestDate()
{
Date d1; // 调用无参构造函数
Date d2(2015, 1, 1); // 调用带参的构造函数
// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
Date d3();
}
如果没有显示定义构造函数,C++编译器会生成一个无参的默认构造函数,一旦显示,编译器不会自动生成了
class Date
{
public:
/*
// 如果用户显式定义了构造函数,编译器将不再生成
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
*/
private:
int _year;
int _month;
int _day;
};
数
生成
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
int main()
{
// 将Date类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函
// 将Date类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再
// 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用
Date d1;
return 0;
}
关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会 生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默 认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的 默认构造函数并没有什么用?? 解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类 型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看 下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员 函数。
class Time
{
public:
Time()
{
cout << "Time()" << endl;
_hour = 0;
_minute = 0;
_second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year;
int _month;
int _day;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
对内置成员不初始化问题有做了修改
内置成员变量在声明的时候可以给默认值
class Time
{
public:
Time()
{
cout << "Time()" << endl;
_hour = 0;
_minute = 0;
_second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
无参数构造函数,全缺省构造函数,我们没有写编译器默认生成的构造函数,都是默认构造函数
class Date
{
public:
Date()
{
_year = 1900;
_month = 1;
_day = 1;
}
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
// 以下测试函数能通过编译吗?
void Test()
{
Date d1;
}
四道栈和队列的题
解决的代码
#include<stdbool.h> #include<assert.h> class Stack { public: Stack(int capacity = 3) { _array = (char*)malloc(sizeof(char) * 3); _capacity = capacity; _sz = 0; } void push(char str) { if (_capacity == _sz) { char*tmp = (char*)realloc(_array, sizeof(char) * _capacity * 2); _array = tmp; _capacity *= 2; } _array[_sz++] = str; } bool empty() { return _sz == 0; } void pop() { assert(!empty()); _sz--; } int top() { return _array[_sz - 1]; } private: char* _array; int _capacity; int _sz; }; class Solution { public: bool isValid(string s) { Stack sl; int n = s.size(); int i = 0; while(i<n) { if(s[i]=='(' || s[i]=='[' || s[i]=='{') { sl.push(s[i]); } else { if(sl.empty()) { return false; } char top=sl.top(); sl.pop(); if((s[i]==']' && top!='[')||(s[i]=='}'&& top!='{')||(s[i]==')'&&top!='(')) { return false; } } i++; } return sl.empty(); } };
可以用C语言试一下
解决的代码
#include<iostream> #include<assert.h> class Queue { public: void push(int x) { qnode* newnode = new qnode; newnode->next = nullptr; newnode->data = x; if (head == nullptr) { assert(tail == nullptr); head = tail = newnode; } else { tail->next = newnode; tail = newnode; } sz++; } void pop() { if (head->next == nullptr) { head->next = nullptr; free(head->next); head = tail = nullptr; } else { qnode* next = head->next; // free(head); head = next; } sz--; } int front() { return head->data; } int back() { return tail->data; } bool empty() { return sz == 0; } int size() { return sz; } private: typedef struct queuenode { struct queuenode* next; int data; }qnode; qnode* head = nullptr; qnode* tail = nullptr; int sz = 0; }; class MyStack { public: void push(int x) { if (!q1.empty()) { q1.push(x); } else { q2.push(x); } } int pop() { Queue*empty = &q1; Queue*noempty = &q2; if (!q1.empty()) { empty = &q2; noempty = &q1; } while ((*noempty).size() > 1) { (*empty).push((*noempty).front()); (*noempty).pop(); } int front = (*noempty).front(); (*noempty).pop(); return front; } int top() { if (!q1.empty()) { return q1.back(); } else { return q2.back(); } } bool empty() { return q1. empty() && q2.empty(); } Queue q1; Queue q2; };
自己可以用C语言试一下
代码
#include<stdbool.h> #include<assert.h> #include<stdlib.h> class Stack { public: Stack(int capacity = 3) { _array = (char*)malloc(sizeof(char) * 3); _capacity = capacity; _sz = 0; } void push(char str) { if (_capacity == _sz) { char* tmp = (char*)realloc(_array, sizeof(char) * _capacity * 2); _array = tmp; _capacity *= 2; } _array[_sz++] = str; } bool empty() { return _sz == 0; } void pop() { assert(!empty()); _sz--; } int top() { return _array[_sz - 1]; } private: char* _array; int _capacity; int _sz; }; class MyQueue{ public: void push(int x) { pushst.push(x); } int peek() { if ((&popst)->empty()) { while (!(&pushst)->empty()) { popst.push((&pushst)->top()); (&pushst)->pop(); } } int top = (&popst)->top(); return top; } int pop() { int front = peek(); (&popst)->pop(); return front; } bool empty() { return (&popst)->empty() && (&pushst)->empty(); } private: Stack pushst;//入队列 Stack popst;//出队列 }; /** * Your MyStack object will be instantiated and called as such: * MyStack* obj = new MyStack(); * obj->push(x); * int param_2 = obj->pop(); * int param_3 = obj->top(); * bool param_4 = obj->empty(); */
C语言自己尝试完成一下
代码
#include<iostream> #include<stdlib.h> class MyCircularQueue { public: MyCircularQueue(int k) { _a = (int*)malloc(sizeof(int) * (k + 1)); _rear = _front = 0; _k = k; } bool isEmpty() { return _rear == _front; } bool isFull() { return (_rear + 1) % (_k + 1) == _front; } bool enQueue(int value) { if (isFull()) { return false; } _a[_rear++] = value; _rear = _rear % (_k + 1); return true; } bool deQueue() { if (isEmpty()) { return false; } _front++; _front = _front % (_k + 1); return true; } int Front() { if(isEmpty()) { return -1; } return _a[_front]; } int Rear() { if(isEmpty()) { return -1; } return _a[(_rear - 1 + _k+1) % (_k+1)]; } private: int* _a; int _rear; int _front; int _k; }; /** * Your MyCircularQueue object will be instantiated and called as such: * MyCircularQueue* obj = new MyCircularQueue(k); * bool param_1 = obj->enQueue(value); * bool param_2 = obj->deQueue(); * int param_3 = obj->Front(); * int param_4 = obj->Rear(); * bool param_5 = obj->isEmpty(); * bool param_6 = obj->isFull(); */
自己尝试用C语言实现
#include<iostream>
#include<stdlib.h>
class MyCircularQueue {
public:
MyCircularQueue(int k) {
_a = (int*)malloc(sizeof(int) * (k + 1));
_rear = _front = 0;
_k = k;
}
bool isEmpty() {
return _rear == _front;
}
bool isFull() {
return (_rear + 1) % (_k + 1) == _front;
}
bool enQueue(int value) {
if (isFull())
{
return false;
}
_a[_rear++] = value;
_rear = _rear % (_k + 1);
return true;
}
bool deQueue() {
if (isEmpty())
{
return false;
}
_front++;
_front = _front % (_k + 1);
return true;
}
int Front() {
if(isEmpty())
{
return -1;
}
return _a[_front];
}
int Rear() {
if(isEmpty())
{
return -1;
}
return _a[(_rear - 1 + _k+1) % (_k+1)];
}
private:
int* _a;
int _rear;
int _front;
int _k;
};
> 自己尝试用C语言实现