静态函数 静态数据成员与静态成员函数 为什么虚函数必须是非静态成员函数 构造函数能为static吗

合集下载

C++类静态成员与类静态成员函数详解

C++类静态成员与类静态成员函数详解

C++类静态成员与类静态成员函数详解当将类的某个数据成员声明为static时,该静态数据成员只能被定义⼀次,⽽且要被同类的所有对象共享。

各个对象都拥有类中每⼀个普通数据成员的副本,但静态数据成员只有⼀个实例存在,与定义了多少类对象⽆关。

静态⽅法就是与该类相关的,是类的⼀种⾏为,⽽不是与该类的实例对象相关。

静态数据成员的⽤途之⼀是统计有多少个对象实际存在。

静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的。

也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建⼀个类的对象则静态数据成员都要被重新初始化。

静态成员不可在类体内进⾏赋值,因为它是被所有该类的对象所共享的。

你在⼀个对象⾥给它赋值,其他对象⾥的该成员也会发⽣变化。

为了避免混乱,所以不可在类体内进⾏赋值。

数据类型类名::静态数据成员名=初值不能⽤参数初始化表对静态成员初始化。

⼀般系统缺省初始为0。

静态成员是类所有的对象的共享的成员,⽽不是某个对象的成员。

它在对象中不占⽤存储空间,这个属性为整个类所共有,不属于任何⼀个具体对象。

所以静态成员不能在类的内部初始化,⽐如声明⼀个学⽣类,其中⼀个成员为学⽣总数,则这个变量就应当声明为静态变量,应该根据实际需求来设置成员变量。

复制代码代码如下:#include "iostream"using namespace std;class test{private:int x;int y;public:static int num;static int Getnum(){x+=5; // 这⾏代码是错误的,静态成员函数不能调⽤⾮静态数据成员,要通过类的对象来调⽤。

num+=15;return num;}};int test::num = 10;int main(void){test a;cout<<test::num<<endl; //10test::num = 20;cout<<test::num<<endl; //20cout<<test::Getnum()<<endl; //35cout<<a.Getnum()<<endl; //50system("pause");return 0;}通过上例可知: x+=5; // 这⾏代码是错误的静态函数成员必须通过对象名来访问⾮静态数据成员。

C++类中的静态成员变量和静态成员函数的作用

C++类中的静态成员变量和静态成员函数的作用

数据成员可以分静态变量、非静态变量两种.静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中..一个类中也可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..分两个方面来总结,第一方面主要是相对于面向过程而言,即在这方面不涉及到类,第二方面相对于面向对象而言,主要说明static在类中的作用。

一、在面向过程设计中的static关键字1、静态全局变量定义:在全局变量前,加上关键字static 该变量就被定义成为了一个静态全局变量。

特点:A、该变量在全局数据区分配内存。

B、初始化:如果不显式初始化,那么将被隐式初始化为0(自动变量是随机的,除非显式地初始化)。

C、访变量只在本源文件可见,严格的讲应该为定义之处开始到本文件结束。

例〔摘于C++程序设计教程---钱能主编P103〕://file1.cpp//Example 1#include <iostream.h>void fn();static int n; //定义静态全局变量void main(){n=20;cout < <n < <endl;fn();}void fn(){n++;cout < <n < <endl;}D、文件作用域下声明的const的常量默认为static存储类型。

静态变量都在全局数据区分配内存,包括后面将要提到的静态局部变量。

对于一个完整的程序,在内存中的分布情况如以下图:代码区全局数据区堆区栈区一般程序的由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。

C++静态成员变量和静态成员函数的使用方法总结

C++静态成员变量和静态成员函数的使用方法总结

C++静态成员变量和静态成员函数的使⽤⽅法总结⼀.静态成员变量:类体中的数据成员的声明前加上static关键字,该数据成员就成为了该类的静态数据成员。

和其他数据成员⼀样,静态数据成员也遵守public/protected/private访问规则。

同时,静态数据成员还具有以下特点:1.静态数据成员的定义。

静态数据成员实际上是类域中的全局变量。

所以,静态数据成员的定义(初始化)不应该被放在头⽂件中。

其定义⽅式与全局变量相同。

举例如下:xxx.h⽂件class base{private:static const int _i;//声明,标准c++⽀持有序类型在类体中初始化,但vc6不⽀持。

};xxx.cpp⽂件const int base::_i=10;//定义(初始化)时不受private和protected访问限制.备注:不要在头⽂件中定义(初始化)静态数据成员。

在⼤多数的情况下,这样做会引起重复定义这样的错误。

即使加上#ifndef #define #endif或者#pragma once也不⾏。

2.静态数据成员被类的所有对象所共享,包括该类派⽣类的对象。

即派⽣类对象与基类对象共享基类的静态数据成员。

举例如下:class base{public :static int _num;//声明};int base::_num=0;//静态数据成员的真正定义class derived:public base{};main(){base a;derived b;a._num++;cout<<"base class static data number _numis"<<a._num<<endl;b._num++;cout<<"derived class static data number _numis"<<b._num<<endl;} // 结果为1,2;可见派⽣类与基类共⽤⼀个静态数据成员。

二级C++-12

二级C++-12

二级C++-12(总分:100.00,做题时间:90分钟)一、单项选择题(总题数:40,分数:40.00)1.程序流程图中带有箭头的线段表示的是______。

(分数:1.00)A.图元关系B.数据流C.控制流√D.调用关系解析:[解析] 在数据流图中,用标有名字的箭头表示数据流。

在程序流程图中,用标有名字的箭头表示控制流。

所以选择C。

2.结构化程序设计的基本原则不包括______。

(分数:1.00)A.多态性√B.自顶向下C.模块化D.逐步求精解析:[解析] 结构化程序设计的思想包括:自顶向下、逐步求精、模块化、限制使用goto语句,所以选择A。

3.软件设计中模块划分应遵循的准则是______。

(分数:1.00)A.低内聚低耦合B.高内聚低耦合√C.低内聚高耦合D.高内聚高耦合解析:[解析] 软件设计中模块划分应遵循的准则是高内聚低偶合、模块大小规模适当、模块的依赖关系适当等。

模块的划分应遵循一定的要求,以保证模块划分合理,并进一步保证以此为依据开发出的软件系统可靠性强,易于理解和维护。

模块之间的耦合应尽可能的低,模块的内聚度应尽可能的高。

4.在软件开发中,需求分析阶段产生的主要文档是______。

(分数:1.00)A.可行性分析报告B.软件需求规格说明书√C.概要设计说明书D.集成测试计划解析:[解析] A错误,可行性分析阶段产生可行性分析报告。

C错误,概要设计说明书是总体设计阶段产生的文档。

D错误,集成测试计划是在概要设计阶段编写的文档。

B正确,软件需求规格说明书是后续工作如设计、编码等需要的重要参考文档。

5.算法的有穷性是指______。

(分数:1.00)A.算法程序的运行时间是有限的√B.算法程序所处理的数据量是有限的C.算法程序的长度是有限的D.算法只能被有限的用户使用解析:[解析] 算法原则上能够精确地运行,而且人们用笔和纸做有限次运算后即可完成。

有穷性是指算法程序的运行时间是有限的。

C++虚函数及虚函数表解析

C++虚函数及虚函数表解析

C++虚函数及虚函数表解析虚函数的定义: 虚函数必须是类的⾮静态成员函数(且⾮构造函数),其访问权限是public(可以定义为private or proteceted,但是对于多态来说,没有意义。

),在基类的类定义中定义虚函数的⼀般形式: virtual 函数返回值类型虚函数名(形参表) { 函数体 } 虚函数的作⽤是实现动态联编,也就是在程序的运⾏阶段动态地选择合适的成员函数,在定义了虚函数后, 可以在基类的派⽣类中对虚函数重新定义(形式也是:virtual 函数返回值类型虚函数名(形参表){ 函数体 }),在派⽣类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。

以实现统⼀的接⼝,不同定义过程。

如果在派⽣类中没有对虚函数重新定义,则它继承其基类的虚函数。

当程序发现虚函数名前的关键字virtual后,会⾃动将其作为动态联编处理,即在程序运⾏时动态地选择合适的成员函数。

实现动态联编需要三个条件: 1、必须把需要动态联编的⾏为定义为类的公共属性的虚函数。

2、类之间存在⼦类型关系,⼀般表现为⼀个类从另⼀个类公有派⽣⽽来。

3、必须先使⽤基类指针指向⼦类型的对象,然后直接或者间接使⽤基类指针调⽤虚函数。

定义虚函数的限制: (1)⾮类的成员函数不能定义为虚函数,类的成员函数中静态成员函数和构造函数也不能定义为虚函数,但可以将析构函数定义为虚函数。

实际上,优秀的程序员常常把基类的析构函数定义为虚函数。

因为,将基类的析构函数定义为虚函数后,当利⽤delete删除⼀个指向派⽣类定义的对象指针时,系统会调⽤相应的类的析构函数。

⽽不将析构函数定义为虚函数时,只调⽤基类的析构函数。

(2)只需要在声明函数的类体中使⽤关键字“virtual”将函数声明为虚函数,⽽定义函数时不需要使⽤关键字“virtual”。

(3)如果声明了某个成员函数为虚函数,则在该类中不能出现和这个成员函数同名并且返回值、参数个数、参数类型都相同的⾮虚函数。

C++中静态成员函数与非静态成员函数的区别

C++中静态成员函数与非静态成员函数的区别

C++中静态成员函数与⾮静态成员函数的区别静态成员函数与⾮静态成员函数的区别数据成员:静态数据成员是类的⼀部分,为类的所有实例共享(静态区);⾮静态数据成员,类的每个实例都有⼀份拷贝(动态区)。

静态数据成员的访问:静态数据成员是类的⼀部分,在产⽣任何实例之前已经存在,通过类名::静态成员变量名访问。

函数成员(都在代码区):静态函数成员与⾮静态函数成员都为类所有,对象并不存在函数的拷贝。

静态成员函数和⾮静态成员函数的根本区别在于⾮静态函数由对象名.或者对象指针->调⽤,调⽤时编译器会向函数传递this指针;静态成员函数则有类名::或者对象名.调⽤,编译器不向函数传递this指针,不识别对象个体,经常⽤来操作类的静态数据成员,要访问类的⾮静态成员可以通过对象来实现。

内存⾓度分析:类的静态成员(数据成员和函数成员)为类本⾝所有,在类加载的时候就会分配内存,可以通过类名直接访问;⾮静态成员(数据成员和函数成员)属于类的实例所有,所以只有在创建类的实例的时候才会分配内存,并通过实例去访问。

注意:类的静态数据成员是静态存储,它是静态⽣存周期,必须进⾏初始化。

注意:静态数据成员的初始化在类体外进⾏,前⾯不加static以免与⼀般静态变量或者对象混淆。

静态成员函数访问⾮静态成员报错:类的静态成员在类加载的时候就已经分配内存,⽽此时类的⾮静态成员尚未分配内存,访问内存中不存在的东西⾃然会出错。

例⼦:#includeusing namespace std;class Test{public:Test(int a){ A = a; ++B;}static void smf(Test tt);private:int A;static int B;};void Test::smf(Test tt){cout << "tt.A : " << tt.A << endl; //静态成员函数中通过对象来引⽤⾮静态成员cout << "Test::B : " << Test::B << endl;cout << "tt.B : " << tt.B << endl;}int Test::B = 0; //静态数据成员初始化的格式<数据类型><类名>::<静态数据成员名>=<值>int main(){Test t1(100);Test t2(200);Test::smf(t1);Test::smf(t2);//静态成员函数调⽤时不⽤对象名system("pause");return 0;}感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

静态函数 静态数据成员与静态成员函数 为什么虚函数必须是非静态成员函数 构造函数能为static吗

静态函数 静态数据成员与静态成员函数 为什么虚函数必须是非静态成员函数 构造函数能为static吗

静态函数静态数据成员与静态成员函数为什么虚函数必须是非静态成员函数构造函数能为static吗?2009-07-05 14:27静态函数用static声明的函数是静态函数。

静态函数可以分为全局静态函数和类的静态成员函数。

Static关键字在类中,用static声明的成员变量为静态成员变量,它为该类的公用变量,在第一次使用时被初始化,对于该类的所有对象来说,static成员变量只有一份。

用static声明的方法是静态方法,在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。

静态方法不再是针对于某个对象调用,所以不能访问非静态成员。

可以通过对象引用或类名(不需要实例化)访问静态成员C++类静态数据成员与类静态成员函数函数调用的结果不会访问或者修改任何对象(非static)数据成员,这样的成员声明为静态成员函数比较好。

且如果static int func(....)不是出现在类中,则它不是一个静态成员函数,只是一个普通的全局函数,只不过由于static的限制,它只能在文件所在的编译单位内使用,不能在其它编译单位内使用。

静态成员函数的声明除了在类体的函数声明前加上关键字static,以及不能声明为const或者volatile之外,与非静态成员函数相同。

出现在类体之外的函数定义不能制定关键字static。

静态成员函数没有this指针。

在没有讲述本章内容之前如果我们想要在一个范围内共享某一个数据,那么我们会设立全局对象,但面向对象的程序是由对象构成的,我们如何才能在类范围内共享数据呢?这个问题便是本章的重点:声明为static的类成员或者成员函数便能在类的范围内共同享,我们把这样的成员称做静态成员和静态成员函数。

下面我们用几个实例来说明这个问题,类的成员需要保护,通常情况下为了不违背类的封装特性,我们是把类成员设置为protected(保护状态)的,但是我们为了简化代码,使要说明的问题更为直观,更容易理解,我们在此处都设置为public。

《面向对象程序设计C++》期末试卷及标准答案(A)

《面向对象程序设计C++》期末试卷及标准答案(A)

《面向对象程序设计C++》期末考试试卷(A)试卷说明:本套试题共四个大题,全部题目都答在答题纸上,写在其他地方均无效。

(答题纸在本套试卷的第10页上)一、选择题(每小题2分,共40分)1、C++是()。

A. 面向对象的程序设计语言B. 面向过程的程序设计语言C. 既支持面向对象的程序设计又支持面向过程的程序设计的混合型语言D. 非结构化的程序设计语言2、面向对象程序设计思想的主要特征中不包括()。

A. 封装性B. 多态性C. 继承性D. 功能分解,逐步求精3、若定义:string str; 当语句cin>>str; 执行时,从键盘输入:Microsoft Visual Studio 6.0!所得的结果是str=()。

A. Microsoft Visual Studio 6.0!B. MicrosoftC. Microsoft VisualD. Microsoft Visual Studio 6.04、考虑下面的函数原型声明:void testDefaulParam(int a,int b=7,char z='*');下面函数调用中,不合法的是()。

A. testDefaulParam(5);B. testDefaulParam(5,8);C. testDefaulParam(5,'#');D. testDefaulParam(0,0,'*');5、下列语句中,将函数int sum(int x, int y)正确重载的是()。

A. float sum(int x, int y);B. int sum(int a, int b);C. float sum(float x, float y);D. double sum(int y, int x);6、下列表示引用的方法中,()是正确的。

已知:int a=1000;A. int &x=a;B. char &y;C. int &z=1000;D. float &t=&a;7、在一个函数中,要求通过函数来实现一种不太复杂的功能,并且要求加快执行速度,选用()。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

静态函数静态数据成员与静态成员函数为什么虚函数必须是非静态成员函数构造函数能为static吗?2009-07-05 14:27静态函数用static声明的函数是静态函数。

静态函数可以分为全局静态函数和类的静态成员函数。

Static关键字在类中,用static声明的成员变量为静态成员变量,它为该类的公用变量,在第一次使用时被初始化,对于该类的所有对象来说,static成员变量只有一份。

用static声明的方法是静态方法,在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。

静态方法不再是针对于某个对象调用,所以不能访问非静态成员。

可以通过对象引用或类名(不需要实例化)访问静态成员C++类静态数据成员与类静态成员函数函数调用的结果不会访问或者修改任何对象(非static)数据成员,这样的成员声明为静态成员函数比较好。

且如果static int func(....)不是出现在类中,则它不是一个静态成员函数,只是一个普通的全局函数,只不过由于static的限制,它只能在文件所在的编译单位内使用,不能在其它编译单位内使用。

静态成员函数的声明除了在类体的函数声明前加上关键字static,以及不能声明为const或者volatile之外,与非静态成员函数相同。

出现在类体之外的函数定义不能制定关键字static。

静态成员函数没有this指针。

在没有讲述本章内容之前如果我们想要在一个范围内共享某一个数据,那么我们会设立全局对象,但面向对象的程序是由对象构成的,我们如何才能在类范围内共享数据呢?这个问题便是本章的重点:声明为static的类成员或者成员函数便能在类的范围内共同享,我们把这样的成员称做静态成员和静态成员函数。

下面我们用几个实例来说明这个问题,类的成员需要保护,通常情况下为了不违背类的封装特性,我们是把类成员设置为protected(保护状态)的,但是我们为了简化代码,使要说明的问题更为直观,更容易理解,我们在此处都设置为public。

以下程序我们来做一个模拟访问的例子,在程序中,每建立一个对象我们设置的类静态成员变自动加一,代码如下:#include <iostream>using namespace std;class Internet{public:Internet(char *name,char *address){strcpy(Internet::name,name);strcpy(Internet::address,address);count++;}static void Internet::Sc()//静态成员函数{cout<<count<<endl;}Internet &Rq();public:char name[20];char address[20];static int count;//这里如果写成static int count=0;就是错误的};Internet& Internet::Rq()//返回引用的成员函数{return *this;}int Internet::count = 0;//静态成员的初始化void vist(){Internet a1("中国软件开发实验室","");Internet a2("中国软件开发实验室","");}void fn(Internet &s){cout<<s.Rq().count;}void main(){cout<<Internet::count<<endl;//静态成员值的输出vist();Internet::Sc();//静态成员函数的调用Internet b("中国软件开发实验室","");Internet::Sc();fn(b);cin.get();}上面代码我们用了几种常用的方式建立对象,当建立新对象并调用其构造函数的时候,静态成员cout便运行加1操作,静态成员的初始化应该在主函数调用之前,并且不能在类的声明中出现,通过运行过程的观察我们发现,静态成员count 的状态并不会随着一个新的对象的新建而重新定义,尽而我们了解到类的静态成员是属于类的而不是属于哪一个对象的,所以静态成员的使用应该是类名称加域区分符加成员名称的,在上面的代码中就是Internet::count,虽然我们仍然可以使用对象名加点操作符号加成员名称的方式使用,但是不推荐的,静态类成员的特性就是属于类而不专属于某一个对象。

静态成员函数的特性类似于静态成员的使用,同样与对象无关,调用方法为类名称加域区分符加成员函数名称,在上面的代码中就是Internet::Sc();静态成员函数由于与对象无关系,所以在其中是不能对类的普通成员进行直接操作的。

如果上面的 static void Internet::Sc()修改成为:static void Internet::Sc()//静态成员函数{cout<<name<<endl;//错误cout<<count<<endl;}静态成员函数与普通成员函数的差别就在于缺少this指针,没有这个this指针自然也就无从知道name是哪一个对象的成员了。

根据类静态成员的特性我们可以简单归纳出几点,静态成员的使用范围:1.用来保存对象的个数。

2.作为一个标记,标记一些动作是否发生,比如:文件的打开状态,打印机的使用状态,等等。

3.存储链表的第一个或者最后一个成员的内存地址。

为了做一些必要的练习,深入的掌握静态对象的存在的意义,我们以前面的结构体的教程为基础,用类的方式描述一个线性链表,用于存储若干学生的姓名,代码如下:#include <iostream>using namespace std;class Student{public:Student (char *name);~Student();public:char name[30];Student *next;static Student *point;};Student::Student(char *name){strcpy(Student::name,name);this->next=point;point=this;}Student::~Student ()//析构过程就是节点的脱离过程{cout<<"析构:"<<name<<endl;if(point==this){point=this->next;cin.get();return;}for(Student *ps=point;ps;ps=ps->next){if(ps->next==this){cout<<ps->next<<""<<this->next<<endl;ps->next=next;//=next也可以写成this->next; cin.get();return;}}cin.get();}Student* Student::point=NULL;void main(){Student *c = new Student("marry");Student a("colin");Student b("jamesji");delete c;Student *fp=Student::point;while(fp!=NULL){cout<<fp->name<<endl;fp=fp->next;}cin.get();}从上面的代码来看,原来单纯结构化编程需要的一个链表进入全局指针在这里被类的静态成员指针所替代(类的静态成员完全可以替代全局变量),这个例子的理解重点主要是要注意观察类成员的析构顺序,通过对析构顺序的理解,使用析构函数来进行节点的脱链操作。

为什么虚函数必须是非静态成员函数如果定义为虚函数,那么它就是动态绑定的,也就是在派生类中可以被覆盖的,这与静态成员函数的定义本身就是相矛盾的。

==主要有两个作用:1、管理静态数据成员;2、提供类范围的功能,即不需要对象来实现的功能。

比如Symbian中的NewL/LC方法就是static的==使用static关键字声明的函数成员是静态的,静态成员函数同样也属于整个类,由同一个类的所有对象共同维护,为这些对象所共享。

作为成员函数,它的访问属性可以受到类的严格控制,对于公有的静态函数成员函数,可以通过类名或对象名来调用,但一般情况下建议用对象名来引用静态函数成员(真的吗?)。

注意,一般的成员函数只能通过对象名来调用。

由于一个类的静态成员函数只有一个拷贝,因此它访问对象的数据何函数使受到了限制。

静态成员函数可以直接访问该类的静态数据成员。

而访问非静态数据成员,必须通过参数传递方式得到对象名,然后通过对象名来访问。

可以看到,通过静态函数成员访问非静态成员使相当麻烦的,一般的使用中,它主要用来访问全局变量或同一个类中的静态数据成员,特别是和后者一起使用,达到对同一个类中对象之间共享的数据进行维护的目的。

构造函数不可以定义为static,看了上面,应该可以理解原因。

注意,由于static不是函数类型中的一部分,所以在类定义之外定义静态成员函数时不使用static,在类中定义的静态成员函数是内联的。

一般来说,通过成员名限定比使用对象名访问静态成员要好。

因为静态成员不是对象的成员。

静态成员可以被继承,这时,基类对象和派生类的对象共享该静态成员,除此之外,在类等级中对静态成员的其他特性(例如,静态成员在派生类中的访问权限,在派生类中重载成员函数等)的分析与一般成员类似。

静态成员函数不能被申明为虚函数,静态成员具有外部连接属性,static仅有的含义是使该成员为该类的所有对象共享。

类中的任何成员函数都可以访问静态成员,但静态成员函数只能通过对象名(或指向对象的指针)访问该对象的非静态成员,因为静态成员函数没有this 指针。

虚函数必须是非静态成员函数构造函数不可以定义为static。

相关文档
最新文档