C++封装学习(一)

类的基本知识已经学过了,但是对类的理解还不够深刻,下面摘一些C++远征中的讲解。

类的实例化有两种,一种是从栈中,一种是从堆中。

我们定义一个TV类。

	class TV
	{
	public:
		char name[20];
		int type;

		void changeVol();
		void power();
	};

栈中实例化对象。系统会自动回收内存。

	TV tv;
	TV tv[20];//对象的数组

堆中实例化对象。需要我们手动的释放内存。

<span style="white-space:pre">	</span>TV *p = new TV();
	TV *q = new TV[20];

	delete p;
	delete[]q;

一个类的数组访问成员。

int main()
	{

		TV *p= new TV[5];
		for (int i = 0; i < 5; i++)
		{
			p[i]->type = 0;
			p[i]->changeVol();
		}

		delete []p;
		p = NULL;

		system("pause");//暂停程序

		return 0;
	}


类外定义,内联函数使用关键词inline来定义,下面是一个例子。

inline void fun()
{
	cout << "hello " << endl;
}

其中,区别如下,内联省去了调用和返回。但是要求内联函数是逻辑简单的函数。

在类定义中,将类函数的函数体定义在类内是,就是类内定义。类内定义就是默认为inline内联函数。除了类内定义,当然就有类外定义,就是函数体在类外面。其中有两种情况,同文件类外定义和份文件类外定义。

类内定义如下,在同一个Car.cpp文件下,类的定义和函数全部定义在一个文件中。

class Car
{
public:
	void fun();
	void stop();
	void changeSpeed();

};

void Car::run(){}
void Car::stop(){}
void Car::changeSpeed(){}

实际专业的程序员都会将类定义分文件完成,这样做有很多好处。以下为一个示例,在Car.h中定义类,在Car.cpp中定义函数。

数据的结构,在内存中,分区如图所示。栈区由系统管理,分配和回收不需要程序员关心。

在申明一个类后,不会占用存储。只有在实例化一个对象时,才会在堆或栈中占据空间。若没有对实例化的数据初始化,是非常危险的。所以要对其初始化。为了防止漏初始化和重复初始化,C++设置了构造函数,在对象实例化时自动调用,被调用且仅调用一次,构造函数与类名是相同的,构造函数没有返回值,可以重载,当用户没有定义构造函数时,系统自动生成一个构造函数,如下代码所示。

class Student()
{
public:
	Student(){ m_strName = "jim"; }//无参数的构造函数
private:
	string m_strName;

}
有参数的构造函数下。

class Student()
{
public:
	Student(string name){ m_strName = name; }
private:
	string m_strName;

}
当然,构造函数也是可以重载的。

class Student()
{
public:
	Student(){ m_strName = "Jim"; }
	Student(string name){ m_strName = name; }//重载的构造函数

private:
	string m_strName;
}

初始化列表语法即下面的代码。有几个特性,初始化列表优先于构造函数执行,初始化列表只能用于构造函数,初始化列表可以同时初始化多个数据成员。

class Student()
{
public:
	Student() :m_strName("Jim"), m_iAge(10){}//初始化列表

private:
	string m_strName;
	int m_iAge;
}

初始化列表的必要性。

//初始化列表的必要性
class Circle
{
public:
	Circle(){m_dPi=3.14}//错误,因为是const,不能再复赋值
private:
	const double m_dPi;
};

class Circle
{
public:
	Circle():m_dPi=3.14{ }//正确
private:
	const double m_dPi;
};



下面首先看一段代码。

class Student
{
public:
	Student()
	{
		cout << "Student" << endl;
	}
private:
	string m_strName;
};

int main()
{
	Student stu1;
	Student stu2 = stu1;
	Student stu3(stu1);

	return 0;
}

在main()函数初始化中,将stu1的复制给了stu2和stu3,理论上应该是初始化了三次,那么应该输出三行“student”,但实际运行后法相,只输出一行“student”。这两种实例化方式时调用的是拷贝构造函数,形式如下。在没有定义拷贝构造函数时,系统会自动生成一个拷贝构造函数并调用,这也是为什么上面代码只输出了一行“student”。

class Student
{
public:
	Student(){ m_strName = "Jim"; }
	Student(const Student& stu){}
private:
	string m_strName;
};

析构函数在对象销毁时自动调用,归还系统资源,格式为~类名()。

class Student
{
public:
	Student(){ cout << "Student" << endl; }
	~Student(){ cout << "~Student" << endl; }
private:
	string m_strName;
};

下面一段代码展示了析构函数的重要性。析构函数可以释放掉堆中的内存。


class Student
{
public:
	Student(){ m_pName = new char[20]; }//堆中申请了资源
private:
	char *m_pName;
};





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值