大家都知道C++中类的成员函数默认都提供了this指针,在非静态成员函数中当你调用函数的时候,编译器都会“自动”帮你把这个this指针加到函数形参里去。当然在C++灵活性下面,类还具备了静态成员和静态函数,即
-
2019-05-01 17:17:30
一 点睛
与静态数据成员不同,静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员。
静态成员函数没有this指针。既然它没有指向某一对象,也就无法对一个对象中的非静态成员进行默认访问(即在引用数据时不指定对象名)。
静态成员函数和非静态成员函数的根本区别:非静态成员函数有this指针,而非静态成员函数没有this指针。由此决定了静态成员函数不能访问本类中的非静态成员。
静态成员函数可以直接引用本类中的静态数据成员,静态成员函数主要用来访问静态数据成员,而不访问非静态成员。
假如在一个静态成员函数中有如下语句:
cout<<height<<endl; //若height已声明为static,则引用本类中的静态成员,合法 cout<<width<<endl; //若width是非静态成员,不合法
但并不是说绝对不能引用本类中的非静态成员,只是不能进行默认访问,因为无法知道去找哪个对象。如果一定要引用本类中的非静态成员,应该加对象名和成员运算符".",如:
cout<<a.width<<endl; //引用本类对象a的非静态成员
最好养成这样的习惯:只用静态成员函数引用静态数据成员,而不引用非静态数据成员。
二 实战
1 代码
#include<iostream> using namespace std; class CStudent{ public: CStudent (int n,int s):num(n),score(s){}//定义构造函数 void total(); static double average(); private: int num; int score; static int count; static int sum;//这两个数据成员是所有对象共享的 }; int CStudent::count=0;//定义静态数据成员 int CStudent::sum=0; void CStudent::total(){//定义非静态成员函数 sum+=score; //非静态数据成员函数中可使用静态数据成员、非静态数据成员 count++; } double CStudent::average(){//定义静态成员函数 return sum*1.0/count;//可以直接引用静态数据成员,不用加类名 } int main(){ CStudent stu1(1,100); stu1.total();//调用对象的非静态成员函数 CStudent stu2(2,98); stu2.total(); CStudent stu3(3,99); stu3.total(); cout<< CStudent::average()<<endl;//调用类的静态成员函数,输出99 }
2 运行
[root@localhost charpter02]# g++ 0213.cpp -o 0213 [root@localhost charpter02]# ./0213 99
更多相关内容 -
C++静态成员函数不能调用非静态成员变量(详解)
2020-08-31 21:43:00下面小编就为大家带来一篇C++静态成员函数不能调用非静态成员变量(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
C++静态成员函数访问非静态成员的几种方法
2020-12-22 16:23:45大家都知道C++中类的成员函数默认都提供了this指针,在非静态成员函数中当你调用函数的时候,编译器都会“自动”帮你把这个this指针加到函数形参里去。当然在C++灵活性下面,类还具备了静态成员和静态函数,即 ... -
C++中静态成员函数与静态成员变量(static )
2021-01-20 05:54:09C++中静态成员函数与静态成员变量(static ) 这篇介绍了静态成员函数与静态成员变量,是我的读书笔记,我希望它够简短但又比较全面,起到复习的作用。如果有一些C++知识记不清楚了,它可以帮你很快回忆起来。 复习... -
C++ 中静态成员函数与非静态成员函数的区别
2020-08-30 14:52:34主要介绍了C++ 中静态成员函数与非静态成员函数的区别的相关资料,需要的朋友可以参考下 -
C++ 静态成员函数
2020-02-28 13:25:31在类中,static 不仅可以声明静态成员变量,还可以声明静态成员函数。 1、普通成员函数可以访问所有成员(包括成员变量和成员函数),而静态成员函数只能访问静态成员。 编译器在编译一个普通成员函数时,会隐式地...1、普通成员函数可以访问所有成员(包括成员变量和成员函数),而静态成员函数只能访问静态成员。
编译器在编译一个普通成员函数时,会隐式地增加一个形参 this指针,并把当前对象的地址赋值给这个this指针,所以普通成员函数只能在创建对象后通过对象来调用,因为它需要当前对象的地址。而静态成员函数可以通过类来直接调用,编译器不会为它增加形参 this,它不需要当前对象的地址,所以不管有没有创建对象,都可以调用静态成员函数。
普通成员变量占用对象的内存,静态成员函数没有 this 指针,不知道指向哪个对象,无法访问对象的成员变量,也就是说静态成员函数不能访问普通成员变量,只能访问静态成员变量。
普通成员函数必须通过对象才能调用,而静态成员函数没有 this 指针,无法在函数体内部访问某个对象,所以不能调用普通成员函数,只能调用静态成员函数。
静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。2、和静态成员变量类似,静态成员函数在声明时要加 static,但在定义时不能加 static。静态成员函数一般都是通过类来调用,也可以通过对象来调用,上例仅仅演示了如何通过类来调用。
通过静态成员函数来获得学生的总人数和总成绩:
#include <iostream> using namespace std; class Student{ public: Student(char *name, int age, float score); void show(); public: //声明静态成员函数 static int getTotal(); static float getPoints(); private: static int m_total; //总人数 static float m_points; //总成绩 private: char *m_name; int m_age; float m_score; }; int Student::m_total = 0; float Student::m_points = 0.0; Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ m_total++; m_points += score; } void Student::show(){ cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl; } //定义静态成员函数 int Student::getTotal(){ return m_total; } float Student::getPoints(){ return m_points; } int main(){ (new Student("张三", 15, 90.6)) -> show(); //张三的年龄是15,成绩是90.6 (new Student("李四", 16, 80.5)) -> show(); //李四的年龄是16,成绩是80.5 (new Student("王五", 16, 99.0)) -> show(); //王五的年龄是16,成绩是99 (new Student("赵六", 14, 60.8)) -> show(); //赵六的年龄是14,成绩是60.8 int total = Student::getTotal(); float points = Student::getPoints(); cout<<"当前共有"<<total<<"名学生,总成绩是"<<points<<",平均分是"<<points/total<<endl; //当前共有4名学生,总成绩是330.9,平均分是82.725 return 0; }
总人数 m_total 和总成绩 m_points 由各个对象累加得到,必须声明为 static 才能共享;getTotal()、getPoints() 分别用来获取总人数和总成绩,为了访问 static 成员变量,我们将这两个函数也声明为 static。
在C++中,静态成员函数的主要目的是访问静态成员。getTotal()、getPoints() 当然也可以声明为普通成员函数,但是它们都只对静态成员进行操作,加上 static 语义更加明确。 -
关于C++静态成员函数访问非静态成员变量的问题
2020-09-04 23:55:15静态成员函数不能访问非静态成员,这是因为静态函数属于类而不是属于整个对象,静态函数中的 member可能都没有分配内存。静态成员函数没有隐含的this自变量。所以,它就无法访问自己类的非静态成员 -
C++静态成员函数访问非静态成员的四种方法
2021-07-01 17:00:48大家都知道C++中类的成员函数默认都提供了this指针,在非静态成员函数中当你调用函数的时候,编译器都会“自动”帮你把这个this指针加到函数形参里去。当然在C++灵活性下面,类还具备了静态成员和静态函数,即 class...class A { public: static void test() { m_staticA += 1; } private: static int m_staticA; int m_a };
此时你的test函数只能去访问m_staticA成员,而不能去访问m_a。同学可能会问,这算什么问题?问题都是在应用场景中才能体现的,我一开始也是不以为意,直到我遇到了回调函数这个烦人的问题我才真正静下心来去考虑这个知识点。
先简单说下回调,在座的应该都知道回调的含义,在C中回调主要体现就是回调函数,当然C++中也有仿函数等其他用法,抛开这些,单纯在回调函数这个点上我们进行如下讨论。
由于C++类的成员函数都隐含了this指针,如果我直接注册,比如:
typedef void (A::*FunPtr)(); FunPtr p = A::hello; p();
此时程序会报错,提示信息是你缺少一个this指针,意味着你要真的想使用p,你必须有一个分配好空间的实例才能来调用
typedef void (A::*FunPtr)(); FunPtr p = A::hello; A a; A *pA = new A(); (a.*p)(); (pA->*p)();
当然,如果仅仅是对C++的类静态函数进行回调函数注册,你是不需要考虑this指针的
typedef void (A::*FunPtr)(); FunPtr p = A::test; p();
但问题就是,你此时的静态函数是不能拥有你的成员变量的,看到了吧,问题来了。面对这种需求,我们就真正应该静下心来好好想想,究竟如何才能让静态函数去访问非静态成员变量这个问题了。
有如下四种方法:
- ① 在静态函数的形参表里加上实例的地址;
- ② 在静态函数中使用全局变量;
- ③ 静态成员函数可以访问静态成员,在类是单例类的情况下,可以在创建的时候把
this
指针赋值给那个静态成员,然后在静态成员函数内部访问this
指向的静态成员; - ④ 在静态函数的形参比加上一个
void *
的内存首地址,然后在内部做转换;
具体示例如下:
方法一:
有一个很取巧的办法,就是在静态函数的形参表里加上实例的地址,也就是:
class A { public: static void test(A *a) { a->m_a += 1; } void hello() { } private: static int m_staticA; int m_a };
这样在你回调函数的时候,你可以通过这个来让本身不能访问成员非静态变量的静态函数(太拗口)来访问非静态成员变量。
方法二:
其实这个方法在GLIB中用的很多,就是在静态函数中使用全局变量,即:
A g_a; class A { public: static void test() { g_a.m_a += 1; } void hello() { } private: static int m_staticA; int m_a };
这种方法我们了解就好,全局变量我们并不推荐。
方法三:
静态成员函数不能访问非静态成员,但别忘了,静态成员函数可以访问静态成员,在类是单例类的情况下,可以在创建的时候把
this
指针赋值给那个静态成员,然后在静态成员函数内部访问this
指向的静态成员:class A { public: A() { m_gA = this; } static void test() { m_gA.m_a += 1; } void hello() { } private: static int m_staticA; static A *m_gA; int m_a };
方法四:
和方法一比较像,但他的方向思想更多的是针对内存块这个概念,意思就是在静态函数的形参比加上一个
void *
的内存首地址,然后在内部做转换:class A { public: static void test(void *pData) { A *a = static_cast<A*>(pData); a->m_a += 1; } void hello() { } private: static int m_staticA; int m_a }; A a; test(&a);
如上,我整理了4种方法,当然方法还有很多,其实绕了这么大远路,我们的希望就是不破坏回调函数整洁的函数接口(即不在回调函数形参列表中加上自己的实例指针)而做的妥协,如果你更喜欢通过改变接口或者通过用Java类似的interface方式来实现,那也没有问题,这里主要就是提供给大家一个思路,C++确实很灵活,我们要用好这把双刃剑 : )
-
C++静态成员函数和普通成员函数的区别
2021-12-12 15:13:35** 静态成员函数和普通成员函数的区别 ** 根据成员函数的创建来看: 静态成员函数为类所有,当类加载创建时,会在内存代码区创建相应函数代码块。 而为了方便内存管理.普通成员函数只有在对象实例化时会在代码区创建...**
静态成员函数和普通成员函数的区别
**
根据成员函数的创建来看:
静态成员函数为类所有,当类加载创建时,会在内存代码区创建相应函数代码块。
而为了方便内存管理.普通成员函数只有在对象实例化时会在代码区创建相应代码块,但是值得一提的是,一旦创建第一个实例化对象,之后再创建对象,普通成员函数也不会增加,自始至终都是一个。
但是普通成员函数只能通过类的对象进行调用,即使delete所有的对象,普通成员函数内存也不会被释放,它参与代码区的生命周期。通过函数的调用进行分析
对象创建时,并不包括成员函数,其中在内存模型中所存储的一般为虚函数表指针,虚继承表指针,以及对应的成员变量。
普通成员函数在创建时,会隐式增加一个this指针,对象在调用普通成员函数时,对象会把当前地址传给this指针,这就是为什么能在当前对象调用对象的成员变量。
类能够调用静态成员函数,对象也能够调用静态成员函数,但是由于静态成员函数并没有包含this指针,所以即使是用对象去调用静态成员函数,也是无法访问对象的成员变量。
class Student { public: void show(); int getOtherPoints(); public: //声明静态成员函数 static int getTotal(); static float getPoints(); static int getAllMessage(); private: static int total; //总人数 static float points; //总成绩 private: char* name; int age; float score; }; int Student::getAllMessage() { //报错没有this指针 所以找不到成员变量 //cout << name << "的年龄是" << age << ",成绩是" << mcore << endl; cout << "当前共有" << total << "名学生,总成绩是" << points << ",平均分是" << points / total << endl; }
-
c++ 静态成员函数调用非静态成员函数/变量
2020-11-01 12:25:42test.h class A { private: static A *s_gA; int m_num; public: A(); ~A(); static void FuncA(); void FuncB(); }; test.cpp #include "test.h" A* A::s_gA = NULL; A::A() { s_gA = this;...< -
c++静态成员函数的作用
2019-06-18 14:08:22静态成员函数主要为了调用方便,不需要生成对象就能调用。 比如: class X { public: void MethodA(); static void MethodB(); } 此时MethodB可以直接调用,X::MethodB(); MethodA必须先生成类对象才能调用... -
C++静态成员变量和静态成员函数的使用方法总结
2020-08-31 17:24:40下面小编就为大家带来一篇C++静态成员变量和静态成员函数的使用方法总结。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
C++ 静态成员函数和非静态成员函数的区别
2019-07-08 10:36:53数据成员: 静态数据成员是类的一...静态函数成员与非静态函数成员都为类所有,对象中并不存在函数的拷贝(每个对象所占用的存储空间只是该对象的数据成员所占用的存储空间,但是在逻辑上函数和数据是一起被封装进... -
C++ 静态成员函数.pdf
2021-08-09 18:56:21C++ 静态成员函数.pdf -
C++静态成员函数访问非静态成员 推荐方法
2019-05-19 16:48:44静态成员函数不能访问非静态成员,但可以访问静态成员,也就是说,如果我们的这个类是个单例,我们完全可以在创建的时候把this指针赋值给那个静态成员,然后在静态成员函数内部就可以放心大胆的使用了。 class A { ... -
c++ 静态成员函数不能访问非静态成员
2019-06-15 11:54:03静态成员函数与类内静态变量相似,属于类,但是独立于对象存在,是共有的。而非静态成员函数属于类,依赖于对象。 静态成员函数没有存在对象的时候,是无法访问到依赖对象的非静态成员函数的,也不存在this指针。 ... -
C++中静态成员函数访问非静态成员的实例
2020-12-31 15:42:53C++中静态成员函数访问非静态成员的实例 实现代码: #include /* 静态成员函数只能访问静态数据成员、静态成员函数和类以外的函数和数据,不能访问非静态数据成员,但静态成员函数或静态数据成员可由任意访问许可... -
C++类静态数成员与类静态成员函数
2014-08-14 11:18:58声明为 static 的类成员或者成员函数便能在类的范围内共同享,我们把这样的成员称 做静态成员和静态成员函数。 -
C++类静态成员与类静态成员函数详解
2021-01-20 06:31:04当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次,而且要被同类的所有对象共享。各个对象都拥有类中每一个普通数据成员的副本,但静态...静态成员不可在类体内进行赋值,因为它是被所有该类的对象所 -
C++静态成员函数访问非静态成员变量的方法
2017-04-06 13:36:52静态成员函数不能访问非静态成员,这是因为静态函数属于类而不是属于整个对象,静态函数中的 member可能都没有分配内存。静态成员函数没有隐含的this自变量。所以,它就无法访问自己类的非静态成员。但我们在一个... -
C++静态成员函数与静态成员变量小结
2011-02-26 07:56:29对C++静态成员函数和静态成员变量的使用方法和内部机制进行的经验总结 -
c++ ——静态成员变量和静态成员函数
2019-11-24 16:03:46c++ 静态成员函数用static 关键字来声明,用于处理静态成员变量,可以用类名来调用,也可以用对象名来调用。 测试代码: #include <iostream> using namespace std; class Point{ public: Po... -
C++ 类静态成员函数
2020-12-06 18:25:14。。。 -
C++中静态成员变量与静态成员函数
2022-04-22 13:46:51C++中静态成员变量与静态成员函数 -
C++类中的静态成员变量和静态成员函数的作用
2011-09-09 16:02:08C++类中的静态成员变量和静态成员函数的作用