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

C++学习笔记13 C++ 类的静态成员

2014-08-26 21:21 330 查看
成员变量的回顾:

通过对象名能够访问public成员变量

每个对象都可以有只属于自己的成员变量

成员变量不能再对象之间共享



类的静态成员:

在C++中可以定义静态成员变量和静态成员函数

静态成员属于整个类所有,不需要依赖任何对象

可以通过类名直接访问public静态成员,但是如果是私有的就不可以。

可以通过对象名访问public静态成员

静态成员函数可以直接访问静态成员变量。普通成员函数也可以直接访问静态成员变量



类的静态成员:

----在定义时直接通过static关键字修饰

----静态成员变量不依赖于任何对象,需要在类外单独分配空间

----语法规则: Type ClassName::VarName;

静态成员函数的定义:

在定义时直接通过static关键字修饰

其余部分与普通成员函数定义相同

#include <iostream>
#include <stdio.h> 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

class Test
{
	private:
		static int cI;
	public:
		static int GetCI()
		{
			return cI;
		}
		static int SetCI(int i)
		{
			cI = i;
		}
		
		void print()
		{
			printf("cI = %d\n",cI);
		}
};

int Test::cI = 0;

int main(int argc, char** argv) {
	
	Test::SetCI(5);
		printf("Test::cI = %d\n", Test::GetCI());
	//Test::print(); Error: 普通成员函数必须由对象调用 
	Test t1;
	t1.print();
	t1.SetCI(10);//静态成员函数被类与它的所有对象共享 
	t1.print(); 
	printf("Test::cI = %d\n", Test::GetCI());
	getchar();
	return 0;
}




这里主要注意一下,类的静态成员变量的初始化,static成员必须在类外初始化。

为什么静态成员不能再类内初始化?

class A
{  
private:
    static int count ; // 类内声明
};

int A::count = 0 ; // 类外初始化,不必再加static关键字

为什么?因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。
什么东西能在类内初始化?

<span style="font-size:14px;color:#000000;"><span style="font-size:12px;">#include <iostream>
#include <stdio.h> 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

class Test
{
	private:
		static int cCount;
		//int a = 0;//error
		int a;
		//const int b = 0;//error 
		const int b;
		static const int c = 0;
	public:
		static int GetI()
		{
			return cCount;
		}
	/*
	Test()
	{
		
		cCount++;
	}
	ERROR: const类型的成员变量b没有初始化 
	*/
	Test():b(4)
	{
		
		cCount++;
	}
	~Test()
	{
		cCount--;
	}
};

int Test::cCount;

void run()
{
	Test ta[100];
	
	printf("对象的数目为:%d\n",Test::GetI());
}

int main(int argc, char** argv) {
	
	
	
	Test t1;
	Test t2;
	printf("对象的数目为:%d\n",Test::GetI());
	run();
	printf("对象的数目为:%d\n",Test::GetI());
	

	getchar();
	return 0;
}

</span>
</span>



class A
{  
private:
    static int count = 0; // 静态成员不能在类内初始化
};




class A
{  
private:
    const int count = 0; // 常量成员也不能在类内初始化
};




class A
{  
private:
    static const int count = 0; // 静态常量成员可以在类内初始化
};




class A
{
	int i = 0;//普通成员变量也编译不通过 
};


静态常量数据成员可以在类内初始化(即类内声明的同时初始化),也可以在类外,即类的实现文件中初始化,不能在构造函数中初始化,也不能在构造函数的初始化列表中初始化;

class A
{
	int i = 0;//普通成员变量也编译不通过 
	static const int j;
	
	A() :j(3) // 编译不通过;静态常量数据成员可以在类内初始化(即类内声明的同时初始化),也可以在类外,
	//即类的实现文件中初始化,不能在构造函数中初始化,也不能在构造函数的初始化列表中初始化;

	{
		
	}
};




静态非常量数据成员只能在类外,即类的实现文件中初始化,也不能在构造函数中初始化,不能在构造函数的初始化列表中初始化;
class A
{
	int i = 0;//普通成员变量也编译不通过 
	static  int j;

	A():j(4) //编译不通过, 静态非常量数据成员只能在类外,即类的实现文件中初始化,也不能在构造函数中初始化,不能在构造函数的初始化列表中初始化;
	{
		
	}

	A()
	{
		j = 4; //编译不通过 
	}
	 
	
};


非静态的常量数据成员不能在类内初始化,也不能在构造函数中初始化,而只能且必须在构造函数的初始化列表中初始化;

class A
{
	
	const int j;//非静态常量数据成员 
	A():j(4) //可以编译通过, 非静态的常量数据成员不能在类内初始化,也不能在构造函数中初始化,而只能且必须在构造函数的初始化列表中初始化;

	{ 
		
	} 

	 
	
};


非静态的非常量数据成员不能在类内初始化,可以在构造函数中初始化,也可以在构造函数的初始化列表中初始化;
class A
{
	
	int i = 0;//error 编译不通过  
	int j;
	
	A()
	{
		j = 0; //可以编译通过 
	} 

	A():j(0)
	{
		
		//可以编译通过  非静态的非常量数据成员不能在类内初始化,可以在构造函数中初始化,也可以在构造函数的初始化列表中初始化;

	}

	 
	
};


有三种类型必须通过初始化列表来实现
1: 非静态 常量(const 常量)
2: 没有默认构造函数的类类型
3: 引用类型

从不同的角度看类的静态成员:
从命名空间的角度:
类的静态成员只是类这个命名空间中的全局变量和全局函数
不同之处只是,类可以对静态成员进行访问权限的限制,而命名空间不行
从面向对象的角度
类的静态成员属于类概念本身
类的所有对象共享相同的静态成员


静态成员的应用:统计某个类的对象的数目:
#include <iostream>
#include <stdio.h> 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

class Test
{
	private:
		static int cCount;
		
		
	public:
		static int GetI()
		{
			return cCount;
		}
	
	Test()
	{
		
		cCount++;
	}
	~Test()
	{
		cCount--;
	}
};

int Test::cCount;

void run()
{
	Test ta[100];
	
	printf("对象的数目为:%d\n",Test::GetI());
}

int main(int argc, char** argv) {
	
	
	
	Test t1;
	Test t2;
	printf("对象的数目为:%d\n",Test::GetI());
	run();
	printf("对象的数目为:%d\n",Test::GetI());
	

	getchar();
	return 0;
}


静态成员函数与普通成员函数的区别:

#include <iostream>
#include <stdio.h> 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

struct C1
{
	int i;
	int j;
	short k;
	short l;
} ;
	
class  C2
{
	
	int i;
	int j;
	short k;
	short l;
} ;

class C3
{
	int i;
	int j;
	int k;
	
	static int c;
public:
	C3()
	{
	}
	void print()
	{
	}
};
	
int static c = 0;

int main(int argc, char** argv) {
	
	C1 c1;
	C2 c2;
	C3 c3;
	
	printf("sizeof(c1) = %d\n",sizeof(c1));
	printf("sizeof(c2) = %d\n",sizeof(c2));
	printf("sizeof(c3) = %d\n",sizeof(c3));
	//c3 的大小与c1 c2 一样,说明静态成员变量存放在静态全局区 

	
	getchar();
	return 0;
}





C++类对象中的成员变量和成员函数是分开存储的

 成员变量

― 普通成员变量:存储于对象中,与struct变量有相同的

内存布局和字节对齐方式

― 静态成员变量:存储于全局数据区中

 成员函数

― 存储于代码段中

C++中的class从面向对象理论出发,将变量和函数集

中定义在一起,用于描述现实世界中的类

从计算机的角度,程序依然由数据段和代码段构成

C++编译器如何完成面向对象理论到计算机程序的转化?

class Test
{
private:
	int mI;
public:
	Test(int i)
	{
	mI = i;
	}
	int getI()
	{
		return mI;
	}
	
	static void Print()
	{
	printf("this is class Test.\n");
	}
};
Test a(10);
a.getI();
Test::Print();

上面的代码经过C++编译器处理后:
struct Test
{
int mI;
};
void Test_initialize(Test *pThis, int i)
{
pThis->mI = i;
}
int Test_getI(Test * pThis)
{
  return  pThis->mI;
}
void Test_Print()
{
printf("this is class Test.\n");
}
Test a;
Test_initialize(&a,10);
Test_getI(&a);
Test_Print();


静态成员函数与普通成员函数的区别

 静态成员函数不包含指向具体对象的指针

 普通成员函数包含一个指向具体对象的指针

C++中类的普通成员函数都隐式包含

一个指向当前对象的this指针。

#include <iostream>
#include <stdio.h> 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

class Test 
{
	int i;
	int j;
	int k;
	
	static int c;
public:
	Test(int i, int j, int k)
	{
	this->i = i; //如果去掉this,将生成乱码,因为 i = i,i的使用范围 在Test()函数中  i 会 屏蔽掉外面的  int i 
	this->j = j;
	this->k = k;
	}
	void print()
	{
	
		printf("对象的地址:%08X\n",this);
		printf("&c = %08X, c = %d\n",&c, c );
		printf("&i = %08X, i = %d\n",&i, i );
		printf("&j = %08X, j = %d\n",&j, j );
		printf("&k = %08X, k = %d\n",&k, k );
	}
	int run( )
	{
		return c;
		
	}
	
	/*
	static void print()
	{
		printf("对象的地址:%08X\n",this);
	}
	编译不通过,说明静态成员函数没有this指针 
	*/
};
	
int Test::c = 0;

int main(int argc, char** argv) {
	
	Test t1(1,2,3);
	printf("t1对象的地址:%08X\n",&t1);
	t1.print();
	Test t2(4,5,6);
	printf("t2对象的地址:%08X\n",&t2);
	t2.print();

	
	getchar();
	return 0;
}




小结:

C++类中可以包含属于类概念的静态成员

 静态成员变量在全局数据区分配空间

 静态成员函数不包含隐藏的this指针

 通过类名可以直接访问静态成员

 通过对象名可以访问静态成员,所有的对象可以共享

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