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 特性
- 静态成员为所有类对象共享,不属于任何具体实例。
- 静态成员变量必须在类外面定义,并且使用的时候,不添加static关键字。
- 静态成员函数里面没有this指针,所以,不能访问任何非静态成员。
- 类静态成员可以使用,类 :: 静态成员或者对象 . 静态成员来访问。
- 静态成员和类的普通类型一样,都有public,protected,private 3种访问级别,也可具有返回值,const修饰符等等。
【问题】
1. 静态成员函数可以调用非静态成员函数吗?
答:不可以。《分析》比如说,static是可读的,它只能访问可读的,但是非静态成员是可读可写,可读一定不能调用可读可写的,权限没有那么高,但是非静态成员是可读可写的,当然可以调用可读的。
2. 非静态成员函数可以调用类的静态成员函数吗?
答;可以。看上面的《分析》
c++中的类和对象(下篇)《第二部分》
链接:https://mp.csdn.net/mdeditor/89077473#
- C++ explicit关键字应用于构造函数
- 从零开始学C++之构造函数与析构函数(一):构造函数、析构函数、赋值与初始化、explicit关键字
- C++中什么情况下要用explicit关键字修饰构造函数?
- c++中关键字explicit用于类的构造函数
- C++当中构造函数前面添加explicit关键字的作用
- C++ explicit关键字应用于构造函数
- 关于QT/C++中explicit关键字和构造函数的*parent参数的简单说明
- C++修饰构造函数的explicit关键字
- C++中的转换函数、explicit关键字与non-explicit-one-argument构造函数
- C++三种构造函数以及explicit和friend关键字
- C++基础---构造函数与关键字explicit
- 从零开始学C++之构造函数与析构函数(一):构造函数、析构函数、赋值与初始化、explicit关键字
- C++修饰构造函数的explicit关键字
- C++ 构造函数的对象初始化列表
- 从Qt谈到C++(一):关键字explicit与构造函数
- C++ 中的关键字-------explicit 修饰构造函数
- C++ 构造函数放置默认转换explicit关键字(2)
- 从零开始学C++之构造函数与析构函数(一):构造函数、析构函数、赋值与初始化、explicit关键字
- C++中构造函数前面的explicit关键字
- C++ explicit关键字应用于构造函数