c++中的类和对象(下篇)《第一部分》 主要包括:《再谈构造函数》《初始化列表》《 explicit关键字》《static成员》

根据前两次的内容,我们已经了解c++是面对对象的,而且大概了解了类中有什么,现在,我们再看看类和对象中还有什么需要我们知道的,因为,这次内容比较多,所以我准备分两次写,这样不至于看到时太多了,还没看就已经厌烦了,下面,正式,进入我们这次内容。

一,再谈构造函数

1 构造函数体的赋值

在创建对象的时候,系统会自己调用构造函数,给对象中的变量一个合适的初始值。
比如下面的一段代码:

  #include<iostream>
using  namespace std;
class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

虽然上面的函数调用了构造函数之后,对象中已经有了一个初始值,但是这并不能将其称为对象值的初始化,构造函数中的语句只能叫做赋初值,而不能叫其初始化因为初始化在函数中,只能初始化一次,而函数可以多次赋值。

2.初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式
以下面的代码为例:

Date(int year, int month, int day)
	:_year(year)
	,	_month(month)
	,_day(day)
	{
			cout << _year << "-" << _month << "-" << _day << endl;
	}

注意:
1. 每一个成员只能在初始化列表中出现一次。
2. 类中包含以下成员必须在初始化列表位置进行初始化。
(1)引用成员变量;
(2)const成员变量;
(3)类类型成员(该类型没有默认的成员函数)

比如下面的例子:

class A
{
public:
	A(int a)
		:_a(a)
	{}
private:
	int _a;
};

class B
{
public:
	B(int a, const int i)
		:_ref(a)
		, _i(i)
		, _aobj(10)
	{}
private:
	int& _ref;
	const int _i;
	A _aobj;
};

3.尽量使用初始化列表进行初始化,因为不管你是否使用初始化列表,对于自定义类型来说,一定会优先使用初始化列表里的值。

class Time
{
public:
	Time(int hous = 1)
		:_hous(hous)
	{
		cout << _hous<< endl;
	}
private:
	int _hous;
};

class Date
{
public:
	Date(int day)
	{}
private:
	int _day;
	Time _t;
};

int main()
{
	Date  d(1);
	return 0;
}

咱们看一下下面的执行结果;
在这里插入图片描述
4.成员变量在类中声明的次序就是在初始化列表中的初始化顺序,与其在初始化列表中的次序无关。

比如下面一段代码:

class Array
{
public:
	Array(int size)
		//:_size(size)
		//, _array((int*)malloc(sizeof(int)*_size))   //要使用与声明中的次序保持一样
		:_array((int*)malloc(sizeof(int)*_size))
		, _size(size)
	{
		cout << _array << _size << endl;
	}
private:
	int* _array;
	int _size;
};

3 explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,还具有类型转换的作用。

我们看下面的一段代码:

class Date
{
public:
	  Date(int year)
		:_year(year)
	{
		cout << _year << endl;
	}
private:
	int _year;
};

int main()
{
	Date d1(2018);
	d1 = 2019;
	return 0;
}

程序这样运行的时候,十一点问题都没有,看看下面的执行程序,
在这里插入图片描述

但是,如果是下面这段代码:

class Date
{
public:
	 explicit  Date(int year)
		:_year(year)
	{
		cout << _year << endl;
	}
private:
	int _year;
};

int main()
{
// 用一个整形变量给日期类型对象赋值
 // 实际编译器背后会用2019构造一个无名对象,最后用无名对象给d1对象进行赋值
	Date d1(2018); 
	d1 = 2019;    //这里会报错
	return 0;
}

看下面的执行程序,
在这里插入图片描述
总结以下:
使用explicit修饰构造函数,将会禁止单参构造函数的隐式转换。

二。static成员

概念:声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数静态的成员变量一定要在类外进行初始化

下面,我们做一个面试题,创建一个类,计算里面出现了多少次类对象。

class A
{
public:
	//A(int scout)
	//	:_scout(scout)  //这里不能使用这个,因为这不是A的非静态成员或基类;
	//{
	//	++_scout
	//}
	A()
	{
		++_scout;
	}
	A(const A& a)
	{
		++_scout;
	}
	static int Getcount()
	{
		return _scout;
	}
private:
	static int _scout;
};

int A::_scout = 0;
int main()
{
	cout << A::Getcount() << endl;
	A a1,a2,a4;
	A a3(a1);
	cout << A::Getcount() << endl;
	return 0;
}

先看一下,下面执行的程序:
在这里插入图片描述
还有下面的一张:
在这里插入图片描述
我相信,由上面这两个执行程序,就可以看出前面的结论,并且还使用了static声明及在类外面实现

2 特性

  1. 静态成员为所有类对象共享,不属于任何具体实例。
  2. 静态成员变量必须在类外面定义,并且使用的时候,不添加static关键字。
  3. 静态成员函数里面没有this指针,所以,不能访问任何非静态成员。
  4. 类静态成员可以使用,类 :: 静态成员或者对象 . 静态成员来访问。
  5. 静态成员和类的普通类型一样,都有public,protected,private 3种访问级别,也可具有返回值,const修饰符等等。

【问题】
1. 静态成员函数可以调用非静态成员函数吗?
答:不可以。《分析》比如说,static是可读的,它只能访问可读的,但是非静态成员是可读可写,可读一定不能调用可读可写的,权限没有那么高,但是非静态成员是可读可写的,当然可以调用可读的。
2. 非静态成员函数可以调用类的静态成员函数吗?
答;可以。看上面的《分析

c++中的类和对象(下篇)《第二部分
链接https://mp.csdn.net/mdeditor/89077473#

猜你喜欢

转载自blog.csdn.net/dpfxaca6/article/details/89046994