C++学习笔记13 C++ 类的静态成员
2014-08-26 21:21
330 查看
成员变量的回顾:
通过对象名能够访问public成员变量
每个对象都可以有只属于自己的成员变量
成员变量不能再对象之间共享
类的静态成员:
在C++中可以定义静态成员变量和静态成员函数
静态成员属于整个类所有,不需要依赖任何对象
可以通过类名直接访问public静态成员,但是如果是私有的就不可以。
可以通过对象名访问public静态成员
静态成员函数可以直接访问静态成员变量。普通成员函数也可以直接访问静态成员变量
类的静态成员:
----在定义时直接通过static关键字修饰
----静态成员变量不依赖于任何对象,需要在类外单独分配空间
----语法规则: Type ClassName::VarName;
静态成员函数的定义:
在定义时直接通过static关键字修饰
其余部分与普通成员函数定义相同
这里主要注意一下,类的静态成员变量的初始化,static成员必须在类外初始化。
为什么静态成员不能再类内初始化?
为什么?因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。
什么东西能在类内初始化?
静态常量数据成员可以在类内初始化(即类内声明的同时初始化),也可以在类外,即类的实现文件中初始化,不能在构造函数中初始化,也不能在构造函数的初始化列表中初始化;
静态非常量数据成员只能在类外,即类的实现文件中初始化,也不能在构造函数中初始化,不能在构造函数的初始化列表中初始化;
非静态的常量数据成员不能在类内初始化,也不能在构造函数中初始化,而只能且必须在构造函数的初始化列表中初始化;
非静态的非常量数据成员不能在类内初始化,可以在构造函数中初始化,也可以在构造函数的初始化列表中初始化;
有三种类型必须通过初始化列表来实现
1: 非静态 常量(const 常量)
2: 没有默认构造函数的类类型
3: 引用类型
从不同的角度看类的静态成员:
从命名空间的角度:
类的静态成员只是类这个命名空间中的全局变量和全局函数
不同之处只是,类可以对静态成员进行访问权限的限制,而命名空间不行
从面向对象的角度
类的静态成员属于类概念本身
类的所有对象共享相同的静态成员
静态成员的应用:统计某个类的对象的数目:
静态成员函数与普通成员函数的区别:
C++类对象中的成员变量和成员函数是分开存储的
成员变量
― 普通成员变量:存储于对象中,与struct变量有相同的
内存布局和字节对齐方式
― 静态成员变量:存储于全局数据区中
成员函数
― 存储于代码段中
C++中的class从面向对象理论出发,将变量和函数集
中定义在一起,用于描述现实世界中的类
从计算机的角度,程序依然由数据段和代码段构成
C++编译器如何完成面向对象理论到计算机程序的转化?
静态成员函数与普通成员函数的区别
静态成员函数不包含指向具体对象的指针
普通成员函数包含一个指向具体对象的指针
C++中类的普通成员函数都隐式包含
一个指向当前对象的this指针。
小结:
C++类中可以包含属于类概念的静态成员
静态成员变量在全局数据区分配空间
静态成员函数不包含隐藏的this指针
通过类名可以直接访问静态成员
通过对象名可以访问静态成员,所有的对象可以共享
同一个类的静态成员
通过对象名能够访问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指针
通过类名可以直接访问静态成员
通过对象名可以访问静态成员,所有的对象可以共享
同一个类的静态成员
相关文章推荐
- C++学习笔记之静态成员
- C++学习笔记-静态成员注意事项
- C++基础学习笔记----第十一课(类的静态成员、对象模型初步认识)
- C++学习笔记1——静态成员
- c++学习笔记(8.类的静态成员)
- c++学习笔记--类的static静态成员
- C++学习笔记--类的静态成员变量和静态成员函数
- 嵌入式开发之C++基础学习笔记5--静态成员,友元,运算符重载,模板,文件流
- [C++学习笔记]--析构函数、静态成员变量、静态成员函数
- c++学习笔记--protected成员
- 【菜鸟C++学习笔记】10.类、对象和成员
- C++ 学习笔记之二:类成员变量的初始化
- C++学习摘要之五:静态成员
- C++学习笔记(二):使用const、static类成员的注意事项
- 【菜鸟C++学习笔记】11.内联函数与const成员函数
- C++学习摘要之五:静态成员 .
- 【C++ rimer 学习笔记】ch13 复制控制
- C++学习摘要之五:静态成员
- 将类成员函数作为线程入口函数——关于C++ 类静态成员的学习
- 2009-11-04 东鳞西爪c++学习日记之静态成员