C++小记(三)

关键字:初始化列表,构造函数和析构函数的调用顺序,对象的动态建立和释放,静态成员变量和静态成员函数

初始化列表:

1)对象初始化列表出现原因
1.必须这样做:
如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,没有默认构造函数。这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,
如果没有初始化列表,那么他将无法完成第一步,就会报错。
 
2、类成员中若有const修饰,必须在对象初始化的时候,给const int m 赋值
当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,
因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。
2)C++中提供初始化列表对成员变量进行初始化

举例说明,穿插构造函数和析构函数的调用顺序:

//inittable.cpp
#include "iostream"
#include "string.h"

using namespace std;

class Birthday
{
private:
	int year;
	int month;
	int day;
public:
	Birthday(int y,int m, int d);
	~Birthday();
	void print();

};

Birthday::Birthday(int y, int m, int d)
{
	cout << "Birthday constructor" << endl;
	year = y;
	month = m;
	day = d;
}

Birthday::~Birthday()
{
	cout << "Birthday destructor" << endl;
}

void Birthday::print()
{
	cout << year << "/" << month << "/" << day << endl;
}

class Student
{
private:
	Birthday m_data;      //成员变量是Birthday类时,Birthday类中有带参构造函数,使用初始化列表解决参数不匹配问题
	char name[20];
	const int age;        //成员变量是常量时,使用初始化列表解决常量初始化赋值
public:
	Student(char *n);
	~Student();
	void print();
};

Student::Student(char *n) :  age(21),m_data(2018, 7, 24)     //初始化列表的使用方法,构造函数调用的顺序与初始化列表顺序无关,与对象声明顺序有关
{
	cout << "Student constructor" << endl;
	strcpy_s(name, n);
}

Student::~Student()                                         //析构函数调用顺序与构造函数调用顺序相反
{
	cout << "Student destructor" << endl;
}

void Student::print()
{
	cout << "name:  " << name << endl;
	cout << "age:  " << age << endl;
	m_data.print();
}

int main()
{
	Student s1("sjw");
	s1.print();
	system("pause");
	return 0;
}

对象的动态建立与释放,new与delete:

1)在软件开发过程中,常常需要动态地分配和撤销内存空间,例如对动态链表中结点的插入与删除。在C语言中是利用库函数malloc和free来分配和撤销内存空间的。C++提供了较简便而功能较强的运算符new和delete来取代malloc和free函数。
注意: new和delete是运算符,不是函数,因此执行效率高。
 
2)虽然为了与C语言兼容,C++仍保留malloc和free函数,但建议用户不用malloc和free函数,而用new和delete运算符。

老样子,代码解决:

#include "iostream"
#include "stdlib.h"

using namespace std;

class Test
{
private:
	int m_a;
public:
	Test();
	Test(int a);
	~Test();
	void print();
};

Test::Test()
{
	cout << "Test constructor1" << endl;
}

Test::Test(int a)
{
	m_a = a;
	cout << "Test construtor2" << endl;
}

Test::~Test()
{
	cout << "Test destructor" << endl;
}

void Test::print()
{
	cout << "m_a = " << m_a << endl;
}

int main()
{
	Test *t1 = (Test *)malloc(sizeof(Test)); //malloc不会创建对象,所以不会调用构造函数
	t1->print();
	free(t1);

	Test *t2 = new Test(666);
	t2->print();

	delete t2;

	system("pause");
	return 0;
}

运行结果如下,malloc不会创建对象,所以不会调用构造函数,new完成对象的动态创建:

需要注意的是:在执行new运算时,如果内存量不足,无法开辟所需的内存空间,目前大多数C++编译系统都使new返回一个0指针值。只要检测返回值是否为0,就可判断分配内存是否成功。

 

静态成员变量和静态成员函数:

静态成员变量:

  1. 关键字 static 可以用于说明一个类的成员,
        静态成员提供了一个同类对象的共享机制
  2. 把一个类的成员说明为 static 时,这个类无论有多少个对象被创建,这些对象共享这个 static 成员
  3. 静态成员局部于类,它不是对象成员,在类的外部进行初始化

静态成员函数:

  1. 静态成员函数数冠以关键字static
  2. 静态成员函数提供不依赖于类数据结构的共同操作,它没有this指针
  3. 在类外调用静态成员函数用 “类名 :: ”作限定词,或通过对象调用
  4. 疑难问题:静态成员函数中,不能使用普通变量,只能使用静态成员变量
#include "iostream"

using namespace std;

class Student
{
private:
	char name[20];
public:
	static int count;      //静态成员变量在类内声明,在类外定义
	Student(char *n);
	static void print();
};

int Student::count = 0;      //类外定义静态处成员变量

Student::Student(char *n)
{
	strcpy_s(name, n);
	count++;
}

void Student::print()
{
	cout << count << endl;
	//cout << name << endl;     静态成员函数无法直接访问普通成员变量
}

int main()
{
	Student *s1 = new Student("sjw");
	Student *s2 = new Student("sjw2");

	//cout << s1->count << endl;     //可以通过对象访问静态成员变量 
	//cout << s2->count << endl;     //也可通过类名访问静态成员变量

	//cout << Student::count << endl;
	s1->print();
	s2->print();					//可以通过对象访问静态成员函数

	Student::print();				//也可通过类名访问静态成员函数

	system("pause");
	return 0;
}

最后稍稍的提一下友元函数:

                  友元函数不是类的内部函数,是一个全局函数,但是可以改变类的私有属性
友元函破坏了类的封装性

猜你喜欢

转载自blog.csdn.net/userkiller/article/details/81191317