C++类&&对象的深入研究(再补充亿点点)

凡事就怕反向flag
(也许是我的文章名称起得太钓鱼执法了?那篇日常的浏览量噌噌得涨哎。。。)


下面我们介绍这章节的最后一部分内容:

静态数据成员和成员函数

静态数据成员

  • 至多初始化一次
  • 若没有显式初始化
    • 静态整型的数据成员缺省初始化为0
    • 静态抽象数据类型(类对象)的数据成员默认调用其缺省构造函数
  • 显式初始化
    • 静态常量整数成员可以在类定义中初始化(const static integral)
    • 其他情况必须在类外部定义和初始化
    • static类型变量不能用构造函数初始化列表进行初始化
#include<iostream>
using namespace std;

class Data{
public:
    Data(int x=1) {cout<<"num1="<<(num1=x)<<endl;}
	//static类型是不能用构造函数初始化列表进行初始化的
	void print() const{cout<<"num2="<<num2<<endl;}
private:
    static int num1;
    const static int num2=10;
    //const static int类型可以直接在定义的时候进行初始化
};

int Data::num1;

class Test{
public:
    Test(){};
    static Data member;
};

Data Test::member(3);
//Data Test::member=Data(3,4);

静态成员函数

  • 没有this指针
  • 不能添加const关键字
  • 不能访问非静态数据成员,不能调用非静态成员函数,只能调用静态的数据成员和成员函数
  • 调用静态成员函数:
    • public static member
      ① 通过对象直接访问
      ② 通过 类名:: 访问
    • private static member
      ① 通过对象调用其他(public)成员函数访问

可以看看下面的栗子
起手,在外部通过 类名:: 直接调用 member.print()
因为member是static类型的成员对象,并且有特意定义的构造函数,所以会立刻进行初始化,输出num1=3

申请obj对象,开辟obj的Data类成员member所需要的空间
因为member是static类型的成员对象,至多初始化一次
所以不会出现num1=3的输出

#include<iostream>
using namespace std;

class Data{
public:
    Data(int x=1) {cout<<"num1="<<(num1=x)<<endl;}
	//static类型是不能用构造函数初始化列表进行初始化的
	void print() const{cout<<"num2="<<num2<<endl;}
private:
    static int num1;
    const static int num2=10;
    //const static int类型可以直接在定义的时候进行初始化
};

int Data::num1;

class Test{
public:
    Test(){};
    static Data member;
};

Data Test::member(3);
//Data Test::member=Data(3,4);

int main()
{
	Test::member.print();
	Test obj;
	obj.member.print();
	system("pause");
	return 0;
}

// Output
num1=3
num2=10
num2=10

最后来看看这两道题

T1

#include <iostream>
using namespace std;
class Student
{
public:
	Student(){++count;};
	~Student(){--count;};
	static int count;
};

int Student::count=0;
Student s;

int main()
{ 
    Student a;
    cout<<a.count<<" students"<<endl;
    Student * b=new Student();
	cout<<b->count<<" students"<<endl;
	{ 
		Student a;
	    cout<<a.count<<" students"<<endl;
    }
    cout<<Student::count<<" students"<<endl;
    delete b;
    cout<<Student::count<<" students"<<endl;
    system("pause");
    return 0;
}

输出:

2 students
3 students
4 students
3 students
2 students

这是怎么回事呢?
首先我们锁定所有产生输出的地方:5处

First.

cout<<a.count<<" students"<<endl;

我们关心count的值
const是static类型,有静态全局性
count的改变出现在构造函数和析构函数
在第一次输出之前,一共申请了两次对象:

Student s;  //全局对象 count=1
Student a;  //mian函数中的对象 count=2

所以输出:

2 students

Second.

Student * b=new Student();
cout<<b->count<<" students"<<endl;

在第二次输出之前,又申请了一个对象b(main函数作用域)count=3

Third. && Fourth.

{ 
	Student a;
	cout<<a.count<<" students"<<endl;
}
cout<<Student::count<<" students"<<endl;

在局部作用域中又申请了一个对象:a,count=4
完成第三次输出后,局部作用域结束,调用析构函数解构局部对象a,count=3

Fifth.

delete b;
cout<<Student::count<<" students"<<endl;

删除对象b,count=2,完成第五次输出


T2

#include <iostream>
using namespace std;
class X
{
	int num;
public:
	X(int i) {num=i;}
	X() {};
	X(X &a) {num=a.num+1;}
	void print(){cout<<num<<endl;}
	X &pro() {return *this;}
	X clone() {return *this;}
};

int main()
{
	X a(0),b(a),c(0),d;
	d=a;
	d.print();
	b.print();	
	X y=b;
	y.print();
    y.pro().print();
	y.clone().print();
	system("pause");
	return 0;
}

输出:

0
1
2
2
3

来解释一下

X a(0),b(a),c(0),d;
d=a;

对象申请上就有大学问:
a.num=0,c.num=0
b的申请调用了拷贝构造函数(用对象初始化对象),b.num=1
然而,d的申请是普通的赋值,d.num=0

X y=b;

y的申请调用了拷贝构造函数(用对象初始化对象),y.num=2

X &pro() {return *this;}
y.pro().print();

pro函数返回引用,考察this指针实现级联函数调用
引用是原对象的影之分身,两者共享内存,所以之后的print输出的是y.num

X clone() {return *this;}
y.clone().print();

clone函数在返回时,调用了拷贝构造函数创建了一个新对象,num=3

Time tmp=y.clone();
//tmp是用对象初始化的,所以调用的拷贝构造函数,num=3
tmp.print();
发布了965 篇原创文章 · 获赞 236 · 访问量 34万+

猜你喜欢

转载自blog.csdn.net/wu_tongtong/article/details/104900981
今日推荐