您的位置:首页 > 编程语言 > C语言/C++

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

2019-04-05 19:58 316 查看

根据前两次的内容,我们已经了解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#

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: