c++一些入门基础,也是初学者容易卡住的地方

本文深入浅出地讲解了C++中类和对象的概念,包括封装性、成员函数、构造函数、拷贝构造函数、析构函数以及运算符重载等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:类和对象:

不说那么多官方概念,我认为类就是更高级于c语言的结构体。

因为它具有封装性,那么什么是封装?简单来说,类里不仅可以有变量,还可以有函数。


不过这个类是声明,不占空间,,像一个模型一样的东西,那么对象就是类的实例化!

我举个例子,如果会弹琴的朋友肯定知道看曲谱和真正弹奏的区别,那么类就是一个谱子,一个谱子可以弹奏多首曲子。

对象就是它的实例化,也就是弹出来这首曲子,曲子里有很多不同的音符,节奏,段落。

题外话:我副职业指弹吉他偷笑


以上是我个人的观点,觉得比较好理解,如果不对欢迎大神来更正。

刚才我说,c++更高级,他当然不是仅仅高级在类里可以写函数,还有很多东西需要慢慢学习。

.访问限定符:


那么来定义一个简单的类:

class Date
{
public:
	void show()
	{
		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}

public:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1;//类实例化出对象
	d1._year = 2017;
	d1._month = 10;
	d1._day = 9;
	d1.show();

	return 0;
}

通过sizeof(d1);得到d1的大小是12,它遵守内存对齐,那么难道成员函数不占空间吗?


注:空类的大小是1个字节,不是0,表示它存在,站位。

二:隐含的this指针:

1.每个成员函数(除了构造函数)都有一个指针形参,叫this,是隐含的。

2.在对象调用成员函数时,对象的地址作实参传递给成员函数的第一个指针形参。


三:默认成员函数:

1.构造函数:

无返回值

函数值与类名相同

对象实例化自动调用

可重载

如不定义,自动生成一个缺省的构造函数

无参,全缺省都认为是缺省构造函数,缺省的只能有一个。

class Date
{
public:
	//Date()//无参
	//{
	//	
	//}

	//Date(int year,int month,int day)//带参
	//{
	//	this->_year = year;
	//	this->_month = month;
	//	this->_day = day;

	//	cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	//}
	

	Date(int year = 2017,int month = 10,int day = 9)//缺省
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;

		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}

	void show()
	{
		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}

private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1(2017,10,1);
	Date d2;

	return 0;
}

d1后面得加括号,d2后面不能加,因为有可能被识别为其他函数。


2.拷贝构造函数:创建对象是用同类对象来初始化。

	Date(const Date& d)
	{
		this->_year = d._year;
		this->_month = d._month;
		this->_day = d._day;
	}
定义了拷贝构造函数之后,

Date d1(2017,10,1);

Date d2(d2);//d2就和d1一样了。

d2的地址传给this,d1引用传递,否则会无穷递归,如图。



注意:必须用引用传参,不引用就会无穷递归,给d1加const。

如果未定义拷贝构造函数,会默认为值拷贝。(值拷贝有时候会有问题,比如有指针指向动态内存开辟的空间,如下)


3.析构函数:当一个对象生命周期结束,调用的成员函数,是清理工作。

类名前加~

无参数无返回值

一个类只有一个析构,未定义会自动生成缺省的

对象生命周期结束,自动调用。

接下来我写一个有指针指向动态内存开辟的空间。

class Seqlist
{
public:
	Seqlist()
	{
		_a = (int*)malloc(sizeof(int)*5);
		_size = 0;
		_capacity = 5;
	}

	void PushBack(int x)
	{
		this->_a[(this->_size)++] = x;
	}

	void print()
	{
		for(size_t i = 0; i < this->_size; i++)
		{
			cout<<this->_a[i]<<endl;
		}
	}

	Seqlist(const Seqlist& s)
	{
		int i = 0;
		for(i = 0; i<s._size; i++)
		{
			this->_a[i] = s._a[i];
		}
	}

	~Seqlist()
	{
		if(this->_a)
		{
			free(this->_a);
			this->_a = NULL;
			this->_size = 0;
			this->_capacity = 0;
		}
	}

private:
	int* _a;
	size_t _size;
	size_t _capacity;
};

int main()
{
	Seqlist s1;
	s1.PushBack(1);
	s1.PushBack(2);
	s1.PushBack(3);
	s1.PushBack(4);
	s1.print();

	Seqlist s2 = s1;
	s2.print();
}

显然这是一个简单的顺序表,实现了尾插的功能。

析构函数最后free掉了_a,并且把它指向NULL,看起来都没有问题,不过如果不写拷贝构造函数,而直接使用的话,会出现问题。



4.运算符重载:为了让自定义类型可以用运算符

operator+合法的运算符构成函数名。

注:c++5个不支持重载的运算符:  .*    ::     sizeof    ?:    .

举例:operator<



class Date
{
public:
	Date(int year = 2017,int month = 10,int day = 9)
	{
		_year = year;
		_month = month;
		_day = day;

		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}

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

private:
	int _year;
	int _month;
	int _day;
};


	
void test()
{
	Date d1(2017,1,25);
	Date d2(2017,1,27);

	cout<<(d1<d2)<<endl;

}


int main()
{
	test();
	return 0;
}

将它写入类内当成成员函数,不然访问不了私有成员。

d1<d2,其实就是d1.operator(&d1,d2),d1的地址传给this,d2引用传递。



赋值运算符重载:


class Date
{
public:
	Date(int year = 2017,int month = 10,int day = 9)
	{
		_year = year;
		_month = month;
		_day = day;

		//cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}

	Date& operator=(const Date& d)
	{
		if(this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}

		return *this;
	}

	void show()
	{
		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}

private:
	int _year;
	int _month;
	int _day;
};


	
void test()
{
	Date d1(2017,1,25);
	Date d2(2017,1,27);

	d2 = d1;
	d2.show();
}


int main()
{
	test();
	return 0;
}

注:引用返回是为了能够连续赋值,比如:d1 = d2 =d3;

if是为了避免两日期相同还赋值浪费时间。

拷贝构造和赋值运算符重载的区别:

Date d4 = d3;//拷贝构造,用同类对象来创建。

d4 = d3;//赋值运算符重载,已存在的两对象。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值