C++课程笔记 类和对象

类概念

结构体:只要属性

类:有属性也有方法

c++可以省略struct  c不行

#include<iostream>
using namespace std;

typedef struct queue1
{
	int a;
	queue1 q() {
		queue1 q(2);
		return q;
	};
	queue1()
	{

	}
	 queue1(int qa)
	{
		a = qa;
	}
}q1;
int main()
{
	queue1 Q1;
	queue1 Qt=Q1.q();
	cout << Qt.q().a<<endl;
	q1 Q2(2);
	cout << Q1.a<<endl;
	cout << Q2.a;
}

struct内部成员默认公有,class默认私有。

public private不分上下

声明定义分离原因:

方便代码阅读

Q1.h:

#include<iostream>
#include<stdbool.h>
using namespace std;
class Cycle
{
public :
	void Init(int n = 4);
	int getr();
private:
	int r;
};

class Point
{
public:
	void Init(int a = 4,int b=4);
	int geta();
	int getb();
private:
	int a;
	int b;
};
void  ifin(Cycle& c, Point& p);

源.cpp:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Q1.h"
void Cycle::Init(int n) {
	r = n;
}
int Cycle::getr() {
	return r;
}
void Point::Init(int m, int n)
{
	a = m;
	b = n;
}
int Point::geta() {
	return a;
}
int Point::getb() {
	return b;
}
void  ifin(Cycle& c,Point& p)
{
	int d1 = p.geta() * p.geta() + p.getb() * p.getb();
	int d2 = c.getr() * c.getr();
	if (d1 > d2)
	{
		cout << "不在" << endl;
	}
	if (d1 <= d2)
	{
		cout << "在" << endl;
	}
	return;
}

test.cpp

#include"Q1.h"

int main()
{
	
	Cycle c1;
	Point p1;
	ifin(c1, p1);
}

类和对象存储:

成员方法存储在公共区方法

成员变量按结构体空间计算

只有成员函数的类大小都是1

构造函数

构造函数完成初始化

class Date {
public:
	Date(int year, int month)
	{
		_year = year;
		_month = month;
		
	}
	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	/
	Date d1(2019, 4);
	d1.print();
}

class Date {
public:
	Date(int year=2020, int month=2,int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date()
	{
		_year = 2019;
		_month = 2;
		_day = 1;
	}
	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	
	Date d1(2021);
	d1.print();
}
class Date {
public:
	Date(int year=2020, int month=2,int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date()
	{
	/*	_year = 2019;
		_month = 2;
		_day = 1;*/
	}
	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	
	Date d1;
	d1.print();
}

全缺省构造可代替无参构造

class Stack
{
public:
	Stack(int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capacity = 4;
	}
	
	void Push(int t)
	{
		_a[_top++] = t;
	}
	void Print()
	{
		for (int i=0;i<_top;i++)
		{
			cout << _a[i] << endl;
		}
	}
private:
	int* _a;
	int  _top;
	int _capacity;
};
int main()
{
	Stack s;
	s.Push(1);
	s.Push(2);
	s.Print();
}

class A {
public:
	A()
	{
		_a = 1;
		cout << "A()构造函数" << endl;
	}
private:
	int _a;
};
class Date {
public:
	/*Date(int year=2020, int month=2,int day=3)
	{
		_year = year;
		_month = month;
		_day = day;
	}*/
	//Date()
	//{
	///*	_year = 2019;
	//	_month = 2;
	//	_day = 1;*/
	//}
	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	A _A;
};
int main()
{
	
	Date d1;
	return 0;
}

默认构造函数内置类型不处理,自定义类型使用自定义类型默认构造函数。

用栈实现队列中,此类就不用写MyQueue构造函数,可以用MyQueue默认生成的,调用Stack默认构造函数。

释放时也会调用Stack默认析构函数,内置类型同样不会处理,自定义类型调用默认析构函数。

class Stack
{
public:
	Stack(int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		cout << "Stack 构造" << endl;
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capacity = 4;
	}
	~Stack()
	{
		cout << "Stack 析构" << endl;
		free(_a);
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}
	void Push(int t)
	{
		_a[_top++] = t;
	}
	void Print()
	{
		for (int i=0;i<_top;i++)
		{
			cout << _a[i] << endl;
		}
	}
private:
	int* _a;
	int  _top;
	int _capacity;
	A _A;
};
class MyQueue {

private:
	Stack s1;
};
int main()
{
	
	MyQueue m1;
	return 0;
}

 

自定义类型构造被内置类型扰乱了 

可以用一下c++11特性解决

class Date {
public:
	/*Date(int year=2020, int month=2,int day=3)
	{
		_year = year;
		_month = month;
		_day = day;
	}*/
	//Date()
	//{
	///*	_year = 2019;
	//	_month = 2;
	//	_day = 1;*/
	//}
	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year=2019;
	int _month=3;
	int _day=3;
	A _A;
};

不传参数就能调用的构造函数是默认构造

析构函数

malloc手动free后销毁

~Stack()
	{
		free(_a);
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}

return时调用析构函数

拷贝构造

class Date {
public:
	Date(int year=2019, int month=2,int day=3)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(Date& d)
	{
		cout << "拷贝构造" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int _year=2019;
	int _month=3;
	int _day=3;
	A _A;
};
void Func1(Date d)
{
	cout << "Func1" << endl;
}
void Func2(Date& d) {
	cout << "Func2" << endl;

}
int main()
{
	
	Date d1;
	
	Func1(d1);
	Func2(d1);
	return 0;
}

只要Func1调用了拷贝构造 

拷贝构造前加const 为了避免错误更改原先对象

 

 

class Stack
{
public:
	Stack(int top,int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		cout << "Stack 构造" << endl;
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{
		cout << "Stack 析构" << endl;
		free(_a);
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}
	void Push(int t)
	{
		_a[_top++] = t;
	}
	void Print()
	{
		for (int i=0;i<_top;i++)
		{
			cout << _a[i] << endl;
		}
	}
private:
	int* _a;
	int  _top;
	int _capacity;
	A _A;
};
int main()
{

	
	Stack s(4,4);
	Stack s2(s);

	return 0;
}

 默认拷贝构造是浅拷贝,函数释放后会free两次,会报错

自定义深拷贝:

class Stack
{
public:
	Stack(int top,int capacity = 4)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		cout << "Stack 构造" << endl;
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}
	Stack(const Stack& s)
	{
		_a = (int*)malloc(sizeof(int) * s._capacity);
		{
			if (_a == nullptr)
			{
				perror("malloc fail");
				exit(-1);
			}
		}
		memcpy(_a, s._a, sizeof(int) * s._top);
		_top = s._top;
		_capacity = s._capacity;
	}
	~Stack()
	{
		cout << "Stack 析构" << endl;
		free(_a);
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}
	void Push(int t)
	{
		_a[_top++] = t;
	}
	void Print()
	{
		for (int i=0;i<_top;i++)
		{
			cout << _a[i] << endl;
		}
	}
private:
	int* _a;
	int  _top;
	int  _capacity;
	//A _A;
};
int main()
{
	
	
	Stack s(0,4);
	s.Push(1);
	s.Push(2);
	s.Print();
	Stack s2(s);
	return 0;
}

 不用写拷贝构造:

运算符重载

class Date {
public:
	Date(int year=2019, int month=2,int day=3)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(Date& d)
	{
		cout << "拷贝构造" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	

	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	bool operator ==(const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;

	}
private:
	int _year=2019;
	int _month=3;
	int _day=3;
	A _A;
};
int main()
{
	
	Date d1(2019,3,2);
	Date d2(2020, 4, 3);
	cout << (d1 == d2) << endl;
    //加括号避免运算符优先级问题
	return 0;
}

 

在 C++ 中,运算符重载函数 bool operator==(const Date& d) 只需要一个参数的原因是,它实际上是在定义一个成员函数。成员函数隐含地有一个指向当前对象(即 this 指针)的参数,因此只需要提供与当前对象进行比较的另一个 Date 对象作为参数。

具体解释:

  1. 隐含的 this 指针: 当你在类内部定义一个成员函数时,这个函数可以访问类的成员变量和成员函数。每个成员函数都有一个隐含的 this 指针,它指向调用该函数的对象。operator== 作为成员函数时,隐含的 this 指针会指向调用 == 运算符的那个对象。

    例如,假设有两个 Date 对象 d1d2,当你写 d1 == d2 时,编译器实际上会将其转换为 d1.operator==(d2)。此时,this 指针指向 d1,而 d2 作为参数传递给 operator== 函数。

  2. 参数个数:

    • 成员函数重载: 对于成员函数形式的运算符重载,== 只需要一个参数,因为 this 指针隐式地传递了调用该运算符的对象。

bool operator ==(const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;

	}
	bool operator>(const Date& d)
	{
		if (_year > d._year)
		{
			return true;
		}
		else if (_year == d._year && _month > d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day > d._day)
		{
			return true;
		}
		return false;
	}
	bool operator >=(const Date& d)
	{
		

计算日期程序: 

class Date {
public:
	Date(int year=2019, int month=2,int day=3)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		cout << "拷贝构造" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	//Date()
	//{
	///*	_year = 2019;
	//	_month = 2;
	//	_day = 1;*/
	//}
	int GetMonthDay(int year, int month)
	{
		static int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if (month == 2 && (year % 4 == 0 && year % 100 != 0 )|| year % 400 == 0)
		{
			return 29;
		}
		return monthday[month];
	}
	Date operator+=(int day)
	{
		_day = day + _day;
		int monthday = GetMonthDay(_year, _month);
		while (_day > monthday)
		{
			++_month;
			if (_month == 13)
			{
				_year++;
				_month = 1;
			}
			_day = _day - monthday;
			monthday = GetMonthDay(_year, _month);
		}
		return *this;
	}
	Date& operator+(int day)
	{
		Date ret(*this);
		ret += (day);
		return ret;
	}
	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	bool operator ==(const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;

	}
	bool operator>(const Date& d)
	{
		if (_year > d._year)
		{
			return true;
		}
		else if (_year == d._year && _month > d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day > d._day)
		{
			return true;
		}
		return false;
	}
	bool operator >=(const Date& d)
	{
		return *this == d || *this > d;
	}
private:
	int _year=2019;
	int _month=3;
	int _day=3;
	A _A;
};
int main()
{
	
	Date d1(2024,9,10);
	Date d2(2019, 3, 2);
	cout << (d1 == d2) << endl;
	cout << (d1 > d2) << endl;
	cout << (d1 >= d2) << endl;
	d1 += 100000;
	Date d3(d1+10);
	
	return 0;
}

 

Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
        return *this;
//return d会出现权限放大
	}
int main()
{
	
	Date d1(2024,9,10);
	Date d2(2019, 3, 2);

	d1 = d2;
	return 0;
}

 

不显示写赋值重载,默认生成的,对自定义类型会浅拷贝

显示写重载,先释放,再开辟空间。

Stack& operator=(const Stack& s)
	{
		if(this!=&s)
{
        free(_a);
		_a = (int*)malloc(sizeof(int) * s._capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		memcpy(_a, s._a, sizeof(int)*s._top);
		_top = s._top;
		_capacity = s._capacity;
		return *this;
}
	}

运算符重载目的是让自定义类型对象可以用运算符。

this指针默认抢了第一个位置

在.h中定义的Print在两个cpp文件都有定义,链接符号表时出现问题

改成静态可以解决问题 不进符号表

声明定义分离也可以解决问题

.h没有定义,不会进符合表

内敛函数在调用的地方直接展开,也可以解决问题。

友元函数:

友元函数没有this指针。 在类中任意位置可以进行友元声明

可以不用去掉private 

权限放大只出现在指针和引用上。 

this指针默认是不能修改的。 

   

初始化列表

 

 

_m不显示写构造,会调用默认构造

类C没有默认构造:

类C有默认构造:

i给rd引用 i给rd的是临时变量,临时变量具有常性。 

加入explicit就不允许隐式类型转换发生了。 

int N = 0;
class A {
public:
	A(int a)
		:_a(a)
	{
		N++;
		cout << "A()构造函数" << endl;
	}
	A(const A& a)
		:_a(a._a)
	{
		N++;
		cout << "A()拷贝构造函数" << endl;

	}
private:
	int _a;
};
void Func(A a)
{

}
int main()
{
	A a1(1);
	A a2 = 2;
	A a3 = a1;
	Func(a3);
	cout << N<<endl;
}

A a3=a1 构造+拷贝构造被优化成了拷贝构造 

 

A::N,指定类域会到命名空间中找, 不指定会先到局部再到全局中找,找不到会报错。

class A {
public:
	A(int a=1)
		:_a(a)
	{
		N++;
		cout << "A()构造函数" << endl;
	}
	A(const A& a)
		:_a(a._a)
	{
		N++;
		cout << "A()拷贝构造函数" << endl;

	}
	 int GetN()
	{
		return N;
	}
private:
	int _a=1;
	static int N ;
};
int A::N = 0;
int main()
{
	A a1;
	A a2 = 2;
	A a3 = a1;
	//Func(a3);
	cout <<a3.GetN()<<endl;
	cout << a2.GetN() << endl;
}

 

应该n数组构造n个对象 

友元类:

class Time {
	friend  class Date;
public:
	Time(int hour=1, int minute=1, int second=1)
		:_hour(hour)
		, _minute(minute)
		, _second(second)
	{

	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date {
public:
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);

	  Date(int year=2019, int month=1,int day=3)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		cout << "拷贝构造" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void SetTime(int hour, int minute, int second)
	{
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
	
private:
	int _year=2019;
	int _month=3;
	int _day=3;
	//A _A;
	Time _t;
};

 内部类:

 

class A {
public:
	A(int a=1)
		:_a(a)
	{
		N++;
		cout << "A()构造函数" << endl;
	}
	A(const A& a)
		:_a(a._a)
	{
		N++;
		cout << "A()拷贝构造函数" << endl;

	}
	class B {
	public:
		void foo()
		{}
	};
	static int GetN()
	{
		return N;
	}
private:
	int _a=1;
	static int N ;
};
int main(){
A::B ab1;
	ab1.foo();
}

匿名对象:

 

创建完直接销毁

 

 

 

 

引用的话需要加const 因为传的是临时变量 具有常性 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南种北李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值