C++中静态成员函数访问非静态成员变量
- 格式:doc
- 大小:20.00 KB
- 文档页数:1
XXX14秋学期《面向对象程序设计》在线作业答案面向对象程序设计14秋学期《面向对象程序设计》在线作业一,单选题1.下列关于this指针的说法,错误的是()。
A。
this指针指向当前正在操作的对象B。
this指针只存在于非静态成员函数中C.在成员函数中对非静态数据成员的访问是通过this指针完成的D.静态成员函数中可以通过this指针访问非静态成员正确答案:D2.已知“int a=10,*p;int *&r=p。
r=*p=20;cout<<a;”,则输出为()。
A。
10B。
20C.不确定值D.程序有错误正确答案:B3.有关重载函数的描述正确的是()。
A.函数名相同的函数就是重载函数B.函数名相同但返回值类型不同的函数就是重载函数C.函数名相同但参数个数或类型不同的函数就是重载函数D.函数功用相同的函数就是重载函数正确答案:C4.在表达式x+y*z中,+是作为成员函数重载的运算符,*是作为非成员函数重载的运算符。
以下叙述中正确的选项是()。
A。
operator+有两个参数,operator*有两个参数B。
operator+有两个参数,operator*有一个参数C。
operator+有一个参数,operator*有两个参数D。
operator+有一个参数,operator*有一个参数正确谜底:C5.以成员函数方式重载运算符“>”,则obj1>obj2被C++编译器解释为()。
A。
operator>(obj1,obj2)B。
(obj1,obj2)C。
obj1.operator>(obj2)D。
obj2.operator>(obj1)正确谜底:C6.下列运算符中,()在C++中不能重载。
A。
:B。
+C。
-D。
<=正确答案:A7.运行以下程序时,如果由键盘输入6514,则输出结果是()。
#includeusingnamespace std。
int main() { int m。
c++的static关键字用法C++中的`static`关键字有多种用法,在不同的场景下都有着不同的含义和作用。
本文将详细介绍C++中`static`关键字的用法及其相关特性,希望能对读者更好地理解和运用这个关键字。
一、`static`关键字概述`static`是C++中的一个关键字,它常用于指定函数、变量、类成员等的作用域和生命周期。
它的主要作用如下:1. 限定变量的作用域。
使用`static`关键字声明的变量具有静态的生存期和块作用域,即在整个程序运行期间都存在,并且只能在声明变量的源文件中访问。
2. 限定函数的作用域。
使用`static`关键字声明的函数具有静态的作用域,即只能在声明它的源文件中调用。
3. 限定类成员的作用域。
使用`static`关键字声明的类成员为静态成员,它不属于类的任何一个对象,而是属于整个类,可以通过类名或类对象来访问。
4. 防止符号重定义。
当在多个源文件中定义同名的全局变量或函数时,使用`static`关键字可以防止它们之间的符号重定义错误。
二、静态变量1. 全局静态变量使用`static`关键字声明的全局变量具有静态生存期和文件作用域,即它在程序运行期间一直存在,而且只能在声明它的源文件中访问。
例如:```cpp//file1.cpp#include <iostream>static int count = 10; //声明全局静态变量countvoid func() {static int i = 5; //局部静态变量i,生命周期为整个程序运行期间std::cout << "i is " << i ;std::cout << " and count is " << count << std::endl;i++;count++;}```在另一个源文件中引用这个全局静态变量,编译器会报错:```cpp//file2.cpp#include <iostream>extern int count; //声明全局变量countvoid func2() {std::cout << "count is " << count << std::endl;}```编译器会报错:undefined reference to `count'。
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; // 这⾏代码是错误的静态函数成员必须通过对象名来访问⾮静态数据成员。
数据成员可以分静态变量、非静态变量两种.静态成员:静态类中的成员加入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++静态成员变量和静态成员函数的使⽤⽅法总结⼀.静态成员变量:类体中的数据成员的声明前加上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#中的静态⽅法如何调⽤静态⽅法C#的类中可以包含两种⽅法:静态⽅法和⾮静态⽅法。
使⽤了static 修饰符的⽅法为静态⽅法,反之则是⾮静态⽅法。
静态⽅法是⼀种特殊的成员⽅法,它不属于类的某⼀个具体的实例,⽽是属于类本⾝。
所以对静态⽅法不需要⾸先创建⼀个类的实例,⽽是采⽤类名.静态⽅法的格式。
1.static⽅法是类中的⼀个成员⽅法,属于整个类,即不⽤创建任何对象也可以直接调⽤!static内部只能出现static变量和其他static⽅法!⽽且static⽅法中还不能使⽤this....等关键字..因为它是属于整个类!2.静态⽅法效率上要⽐实例化⾼,静态⽅法的缺点是不⾃动进⾏销毁,⽽实例化的则可以做销毁。
3.静态⽅法和静态变量创建后始终使⽤同⼀块内存,⽽使⽤实例的⽅式会创建多个内存.4.C#中的⽅法有两种:实例⽅法,静态⽅法.类的⽅法代码只有⼀份,它们的⽣命周期和类是⼀致的.实例⽅法是通过对象名调⽤的,静态⽅法与类关联⽽不是与对象名关联.5.那么在程序中什么地⽅可以利⽤静态字段和静态构造⽅法,通常适⽤于于⼀些不会经常变化⽽⼜频繁使⽤的数据,⽐如连接字符串,配置信息等,当满⾜上⾯所说的两点时,进⾏⼀次读取,以后就可以⽅便的使⽤了,同时也节约了托管资源,因为对于静态成员,⼀个静态字段只标识⼀个存储位置。
对⼀个类⽆论创建了多少个实例,它的静态字段永远都只有⼀个副本(副本我理解为只有⼀块内存静态成员存在于内存,⾮静态成员需要实例化才会分配内存,所以静态成员不能访问⾮静态的成员..因为静态成员存在于内存,所以⾮静态成员可以直接访问类中静态的成员. 公⽤的处理函数,使⽤静态⽅法应该没有问题..牵涉到数据共享,静态变量的函数要多考虑...静态变量要⼩⼼使⽤..静态⽅法原理就是共享代码段共享代码段不会产⽣任何问题因为代码段都是给CPU作为"读取"⽤的,除⾮你进⾏恶意"修改"运⾏时的代码段所以静态⽅法是可以放⼼使⽤的静态变量原理就是共享数据段同上只要没有进⾏"写⼊"操作就不会产⽣问题但是数据通常都是⽤于读和写所以静态变量要注意使⽤下⾯是⼀个使⽤静态⽅法的例⼦ class Class1{[STAThread]static void Main(string[] args){int i = MyClass.Add(3,5); //调⽤静态⽅法Console.WriteLine(i);}}class MyClass{public static int Add(int x,int y ){return x + y ;} }。
static 用法static 用法1. static 变量•定义:在函数内部使用 static 关键字声明的变量称为静态变量。
•特点:–静态变量的生命周期在整个程序运行期间都存在,而不仅仅在函数调用时才存在。
–静态变量存储在静态存储区,不会在函数调用结束后释放内存。
•使用场景:–如果一个变量需要在多次函数调用之间保持其值不变,可以使用静态变量。
–静态变量通常用于计数器或者保存函数的返回值等场景。
•示例代码:#include <>int count() {static int counter = 0;counter++;return counter;}int main() {printf("%d\n", count()); // 输出1printf("%d\n", count()); // 输出2printf("%d\n", count()); // 输出3return 0;}2. static 函数•定义:在函数返回类型前面加上 static 关键字,使函数变为静态函数。
•特点:–静态函数只能在声明它的源文件内部调用,不能被其他源文件使用。
–静态函数不能被其他源文件中的函数调用,从而起到了隐藏的作用。
•使用场景:–当某个函数只在当前源文件内部使用时,可以将其声明为静态函数,以减少命名冲突和提高代码的模块化程度。
•示例代码:#include <>static int multiply(int a, int b) {return a * b;}int main() {int result = multiply(2, 3);printf("%d\n", result); // 输出6return 0;}3. static 类成员•定义:在类中声明的 static 成员属于类本身,而不是类的实例。
•特点:–所有的对象共享同一个静态成员,即静态成员对于所有的对象来说只有一份拷贝。
C语⾔static和const的区别static:1、不考虑类,static的作⽤:1)第⼀个作⽤:隐藏。
使得全局变量和函数对其它⽂件不可见,同时避免了不同⽂件的命名冲突。
2)第⼆个作⽤:默认初始化为0。
未初始化的全局静态变量和局部静态变量都保存在BBS段,BBS段的特点是,程序运⾏之前会⾃动清零。
3)第三个作⽤:保持局部变量内容的持久性。
此变量声明周期是整个程序的声明周期,但是作⽤域只在声明它的函数中。
2、类中的static,表⽰属于某个类单数不属于类的任何特定对象的变量和函数。
1)对于类的静态数据成员:a、类的静态数据成员独⽴于该类的任意对象⽽存在;其值的修改被类的所有对象看见。
b、static数据成员必须在类定义的外部定义,通常放在包含类的⾮内联成员函数定义的⽂件中。
class A{stctic double d = 0.03;//错误};c、但是也有例外,const static 数据成员可以在类的定义体中进⾏初始化,因为const定义时必须初始化。
2)对于类的成员函数:a、static成员函数由于不与任何对象关联,因此它不具备this指针,因此,它⽆法访问属于类对象的⾮静态数据成员,也⽆法访问⾮静态成员函数。
也就是说,类的静态成员函数,只能调⽤该类的其它静态成员函数和静态数据成员。
b、static成员不是任何对象的组成部分,所以成员函数不能被声明为const。
此外,static成员函数也不可以声明为virtual,volatile。
关于静态成员函数的总结:(1)静态成员之间可以相互访问,不能访问⾮静态成员。
⾮静态成员函数可以任意访问静态和⾮静态成员。
(2)静态函数执⾏速度⽐⾮静态函数稍快。
const:1、const定义后就不能修改,因此定义时要初始化。
2、在C语⾔中const buffsize = 10;int buf[buffsize];是错误的;⽽在C++中是正确的。
C中改为const int buffsize;3、使⽤const⽐使⽤#define有更多的优点:1)const常量有数据类型,⽽宏常量没有。
静态函数静态数据成员与静态成员函数为什么虚函数必须是非静态成员函数构造函数能为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选择题填空题一、填空题1、在类中必须声明成员函数的( ),成员函数的( )部分可以写在类外。
[答案]原型实现2、如果需要在被调函数运行期间,改变主调函数中实参变量的值,则函数的形参应该是( )类型或()类型。
[答案]引用指针3、()类只能作为基类使用,而不能声明它的对象。
[答案]抽象4、拷贝构造函数的形参必须是()[答案]本类对象的引用5、进行函数重载时,被重载的同名函数如果都没有用const修饰,则它们的形参()或()必须不同。
[答案]个数类型6、通过一个()对象只能调用它的常成员函数,不能调用其他成员函数。
[答案]常二、选择题1、编译时多态性使用什么获得?(A)A. 重载函数B. 继承C. 虚函数D. B和C2、假定MyClass为一个类,则该类的拷贝构造函数的声明语句为(C)。
A.MyClass(MyClass x)B.MyClass&(MyClass x)C.MyClass(MyClass &x)D.MyClass(MyClass *x)3、列带缺省值参数的函数说明中,正确的说明是(C)1. A. int Fun(int x=1, int y, int z=3);B. int Fun(int x, int y=2, int z);C. int Fun(int x, int y, int z=3);D. int Fun(int x=1, int y, int z);4、下列有关函数重载的叙述中,错误的是(A)A.函数重载就是用相同的函数名定义多个函数B.重载函数的参数列表必须不同C.函数的返回值类型不能用于对重载函数的区分D.const关键字可以用于对重载函数的区分5、在一个函数中,要求通过函数来实现一种不太复杂的功能,并且要求加快执行速度,选用(A)。
A. 内联函数B. 重载函数C. 递归调用D. 嵌套调用6、下列有关C++类的说法中,不正确的是(C)。
A. 类是一种用户自定义的数据类型B. 只有类中的成员函数或类的友元函数才能存取类中的私有成员C. 在类中,如果不做特别说明,所有成员的访问权限均为私有的D. 在类中,如果不做特别说明,所有成员的访问权限均为公用的7、Sample是一个类,执行下面语句后,执行Sample类的构造函数的次数是(D) Sample a[3], *p=new Sample;A.1B.2C.3D.48、关于常数据成员的说法,不正确的是(D)。
一. 选择(共50题,共1分)1. 下列关于类和对象的叙述中,错误的是( )A.一个类只能有一个对象B.对象是类的具体实例C.类是对某一类对象的抽象D.类和对象的关系是一种数据类型与变量的关系2. 当将一个类A或函数f()说明为另一个类B的友元后,类A或函数f()能够直接访问类B的( )。
A.只能是公有成员B.只能是保护成员C.只能是除私有成员之外的任何成员D.任何权限的成员3. 类中定义的成员默认为( )访问属性。
A.publicB.privateC.protectedD.friend4. 一个类的友元不是该类的成员,与该类的关系密切,所以它(D )。
A.有this指针,有默认操作的对象B.没有this指针,可以有默认操作的对象C.有this指针,不能执行默认操作D.没有this指针,也就没有默认操作的对象5. 假定AA为一个类,a为该类私有的数据成员,GetValue()为该类公有函数成员,它返回a的值,x为该类的一个对象,则访问x对象中数据成员a的格式为( )。
A.x.aB.x.a()C.x->GetValue()D.x.GetValue()6. 对于任一个类,用户所能定义的构造函数的个数至多为( )。
A.0B.1C.2D.任意个7. 一个类的析构函数通常被定义为该类的( )成员。
A.私有B.保护C.公用D.友元8. 有如下类声明:class Foo {int bar; };则Foo类的成员bar 是()A.公有数据成员B.公有成员函数C.私有数据成员D.私有成员函数9. 关于封装,下列说法中不正确的是( )。
A.通过封装,对象的全部属性和操作结合在一起,形成一个整体B.通过封装,一个对象的实现细节被尽可能地隐藏起来(不可见)C.通过封装,每个对象都成为相对独立的实体D.通过封装,对象的属性都是不可见的10. 假定AB为一个类,则执行“AB *s=new AB(a,5);”语句时得到的一个动态对象为( )。
判断题1、对空指针不能用delete运算符。
(错误)2、对重载的函数,要求函数类型相同但参数不同。
(错误)3、任何一个对象只能属于一个具体的类。
(正确)4、用new运算符来创建对象时不会调用构造函数。
(错误)5、对重载的函数,要求参数不同或函数类型不同。
(错误)6、在公有继承中,基类中的公有成员和私有成员在派生类中都是可见的。
(错误)7、析构函数可以是虚函数。
(正确)8、无论什么方式的继承,基类的私有成员都不能被派生类访问。
(正确)9、要达到动态联编的效果,基类和派生类的对应函数不仅名字相同,而且返回类型、参数个数和类型也必须相同。
(正确)10、如果派生类没有实现虚函数,那么它将使用他的基类的虚函数。
(正确)11、构造函数可以是虚函数。
(错误)12、指向对象数组的指针不一定必须指向数组的首指针。
(正确)13、对象数组的元素可以是不同类的对象。
(错误)14、对象数组可以赋初值又可以赋值。
(错误)15、一个类的构造函数可以不包含对其子对象的初始化。
(错误)16、在C++中,既允许单继承,又允许多继承。
(正确)17、派生类从基类派生出来,它不能生成新的派生类。
(错误)18、派生类的继承方式只有2种:公有继承和私有继承。
(错误)19、在公有继承中,基类的成员在派生类中都可以直接使用。
(错误)20、在单继承中,派生类中对基类成员的访问也会出现二义性。
(错误)21、解决多继承下二义性问题的方法之一是使用作用域运算符。
(正确)22、作用域运算符(::)只能用来限定成员函数所属的类。
(错误)注:还限制成员变量所属的类。
23、析构函数是一种函数体为空的成员函数。
(错误)24、构造函数和析构函数都不能重载。
(错误)注:构造函数可以重载,析构函数不可以重载(因为析构函数无参数,不可能进行参数区分)。
25、说明或定义对象时,类名前面不需要加class关键字。
(正确)26、对象成员的表示与结构变量成员表示相同,使用运算符.或->。
C语言中,静态函数与非静态函数之间的相互调用是一个常见且重要的问题。
了解这些规则可以帮助程序员更好地理解C语言的函数调用机制,从而提高代码的质量和可维护性。
本文将详细介绍静态函数与非静态函数之间相互调用的规则,希望能够帮助读者对这一问题有更清晰的认识。
一、静态函数的定义静态函数是指在函数前加上static关键字定义的函数。
静态函数的作用域仅限于定义它的文件内部,其他文件无法调用该函数,因此静态函数的作用域是局部的。
二、非静态函数的定义非静态函数即普通函数,没有使用static关键字定义。
非静态函数的作用域为整个程序,可以被其他文件调用。
三、静态函数调用非静态函数1. 静态函数可以直接调用非静态函数,因为非静态函数的作用域为整个程序,可以被任何函数调用。
2. 调用非静态函数时,可以使用函数名直接调用,也可以使用函数指针调用。
静态函数和非静态函数之间的调用方式与普通函数之间的调用方式相同。
四、非静态函数调用静态函数1. 非静态函数无法直接调用定义在其他文件中的静态函数,因为静态函数的作用域仅限于定义它的文件内部。
如果非静态函数想调用其他文件中的静态函数,需要通过外部声明来实现。
2. 外部声明是指在调用静态函数的文件中声明该静态函数。
这样非静态函数就可以通过外部声明来调用其他文件中的静态函数。
五、静态函数调用静态函数1. 静态函数可以直接调用同一文件中的其他静态函数,因为它们的作用域相同。
在同一文件中,静态函数之间的相互调用与普通函数之间的调用方式相同。
2. 静态函数调用其他文件中的静态函数也需要通过外部声明来实现,与非静态函数调用静态函数的方式相同。
六、总结1. 静态函数与非静态函数之间的相互调用需要遵循一定的规则,这些规则主要包括作用域和外部声明两个方面。
2. 静态函数通常用于实现文件内部的辅助功能,而非静态函数用于定义程序的主要逻辑。
了解静态函数与非静态函数的相互调用规则可以帮助程序员更好地组织代码,提高代码的可读性和可维护性。
关于C语⾔中的静态函数在C语⾔中⽤static声明限定外部变量与函数,可以将其后声明的对象的作⽤域限定为被编译源⽂件的剩余部分。
通过static限定外部对象,可以达到隐藏外部对象的⽬的。
如果把函数声明为static类型,则该函数名除了对该函数声明所在的⽂件可见外,其他⽂件都⽆法访问。
也就是只能被本⽂件中的函数调⽤,⽽不能被同⼀程序中的其他⽂件的函数调⽤。
C语⾔程序可以看成由⼀系列外部对象构成,这些外部对象可能是变量或函数。
⽽内部变量是指定义在函数内部的函数参数及变量。
外部变量定义在函数之外,因此可以在许多函数中使⽤。
由于C语⾔不允许在⼀个函数中定义其它函数,因此函数本⾝只能是“外部的”。
由于C语⾔代码是以⽂件为单位来组织的,在⼀个源程序所有源⽂件中,⼀个外部变量或函数只能在某个⽂件中定义⼀次,⽽其它⽂件可以通过extern声明来访问它(定义外部变量或函数的源⽂件中也可以包含对该外部变量的extern声明)。
⽽static则可以限定变量或函数为静态存储。
如果⽤static限定外部变量与函数,则可以将该对象的作⽤域限定为被编译源⽂件的剩余部分。
通过static限定外部对象,可以达到隐藏外部对象的⽬的。
因⽽,static限定的变量或函数不会和同⼀程序中其它⽂件中同名的相冲突。
如果⽤static限定内部变量,则该变量从程序⼀开始就拥有内存,不会随其所在函数的调⽤和退出⽽分配和消失。
C语⾔中使⽤静态函数的好处:1)静态函数会被⾃动分配在⼀个⼀直使⽤的存储区,直到退出应⽤程序实例,避免了调⽤函数时压栈出栈,速度快很多。
2)关键字“static”,译成中⽂就是“静态的”,所以内部函数⼜称静态函数。
但此处“static”的含义不是指存储⽅式,⽽是指对函数的作⽤域仅局限于本⽂件。
使⽤内部函数的好处是:不同的⼈编写不同的函数时,不⽤担⼼⾃⼰定义的函数,是否会与其它⽂件中的函数同名,因为同名也没有关系。
补充1:static变量C/C++中的变量根据作⽤域(知道该名字的程序⽂本区)和⽣命期(程序执⾏过程中对象存在的时间)分为全局变量、静态全局变量、局部变量和静态局部变量。
静态数据成员1.静态数据成员的定义。
静态数据成员实际上是类域中的全局变量。
所以,静态数据成员的定义(初始化)不应该被放在头⽂件中。
其定义⽅式与全局变量相同。
2.在函数体内静态变量具有“记忆”功能,即⼀个被声明为静态的变量在这⼀函数被调⽤的过程中其值维持不变。
与全局变量相⽐,使⽤静态数据成员的优势:静态数据成员没有进⼊程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性。
(静态数据成员属于本类的所有对象共享)。
可以实现信息隐藏。
静态数据成员可以是private成员,⽽全局变量不能。
3.静态数据成员被类的所有对象所共享,包括该类派⽣类的对象。
即派⽣类对象与基类对象共享基类的静态数据成员。
举例如下:1class base{2public :3static int _num;//声明4 };5int base::_num=0;//静态数据成员的真正定义67class derived:public base{8 };910 main()11 {12base a;13 derived b;14 a._num++;15 cout<<"base class static data number _num is"<<a._num<<endl;16 b._num++;17 cout<<"derived class static data number _num is"<<b._num<<endl;18 }// 结果为1,2;可见派⽣类与基类共⽤⼀个静态数据成员。
4.静态数据成员可以成为成员函数的可选参数,⽽普通数据成员则不可以。
举例如下:class base{public :static int _staticVar;int _var;void foo1(int i=_staticVar);//正确,_staticVar为静态数据成员void foo2(int i=_var);//错误,_var为普通数据成员};5.★静态数据成员的类型可以是所属类的类型,⽽普通数据成员则不可以。
一. 选择(共50题,共1分)1. 下列关于类和对象的叙述中,错误的是( )A.一个类只能有一个对象B.对象是类的具体实例C.类是对某一类对象的抽象D.类和对象的关系是一种数据类型与变量的关系2. 当将一个类A或函数f()说明为另一个类B的友元后,类A或函数f()能够直接访问类B的( )。
A.只能是公有成员B.只能是保护成员C.只能是除私有成员之外的任何成员D.任何权限的成员3. 类中定义的成员默认为( )访问属性。
A.publicB.privateC.protectedD.friend4. 一个类的友元不是该类的成员,与该类的关系密切,所以它(D )。
A.有this指针,有默认操作的对象B.没有this指针,可以有默认操作的对象C.有this指针,不能执行默认操作D.没有this指针,也就没有默认操作的对象5. 假定AA为一个类,a为该类私有的数据成员,GetValue()为该类公有函数成员,它返回a的值,x为该类的一个对象,则访问x对象中数据成员a的格式为( )。
A.x.aB.x.a()C.x->GetValue()D.x.GetValue()6. 对于任一个类,用户所能定义的构造函数的个数至多为( )。
A.0B.1C.2D.任意个7. 一个类的析构函数通常被定义为该类的( )成员。
A.私有B.保护C.公用D.友元8. 有如下类声明:class Foo {int bar; };则Foo类的成员bar 是()A.公有数据成员B.公有成员函数C.私有数据成员D.私有成员函数9. 关于封装,下列说法中不正确的是( )。
A.通过封装,对象的全部属性和操作结合在一起,形成一个整体B.通过封装,一个对象的实现细节被尽可能地隐藏起来(不可见)C.通过封装,每个对象都成为相对独立的实体D.通过封装,对象的属性都是不可见的10. 假定AB为一个类,则执行“AB *s=new AB(a,5);”语句时得到的一个动态对象为( )。
C++静态成员函数不能调⽤⾮静态成员变量(详解)其实我们从直观上可以很好的理解静态成员函数不能调⽤⾮静态成员变量这句话因为⽆论是静态成员函数还是静态成员变量,它们都是在类的范畴之类的,及在类的整个⽣存周期⾥始终只能存在⼀份。
然⽽⾮静态成员变量和⾮静态成员函数是针对类的对象⽽⾔。
然⽽从本质上来说类的静态成员函数的函数形参中没有默认的this指针,导致不能调⽤具体实例对象的成员。
下⾯我们来测试⼀下:先在静态成员函数中调⽤静态成员变量:#include <iostream>using namespace std;class vpoet{public:static int a;int b;public:vpoet(int data){b=data;}static void statictestfun1(){cout<<"static a="<<a<<endl;}};int vpoet::a=10;int main(){vpoet *V;V=new vpoet(5);vpoet::statictestfun1();return 0;}调⽤成功,截图如下现在我们再静态成员函数中调⽤⾮静态成员变量#include <iostream>using namespace std;class vpoet{public:static int a;int b;public:vpoet(int data){b=data;}static void statictestfun1(){cout<<"static b="<<b<<endl;}};int vpoet::a=10;int main(){vpoet *V;V=new vpoet(5);vpoet::statictestfun1();return 0;}编译下提⽰了错误:⼤意是在静态成员函数中引⽤了类的⾮静态成员变量b。
静态成员及其函数静态成员静态数据成员静态数据成员的基本介绍:在C++中,静态数据成员是属于类的,一旦声明某个数据成员为静态数据成员,则该类的每个对象都可以访问它。
声明格式:static数据类型数据成员名;为什么使用静态数据成员而不使用全局变量呢?原因是全局变量会带来不安全性,并且破坏了面向对象程序设计的信息隐蔽技术和封装型特点。
在一个类中,无论建立多少个对象,都只有一个静态数据成员的拷贝,从而实现了一个类的不同对象之间数据的共享。
关于静态数据成员的几点说明:1.定义格式:static数据类型数据成员名;2.其初始化与普通数据成员不同,须在类外单独进行初始化,而且初始化要在定义对象之前进行;格式:数据类型类名::静态数据成员名=初始值;3.静态数据成员属于类,而不属于某个对象,可以通过类来访问:类名::静态数据成员名4.对象访问静态数据成员格式:对象名.静态数据成员名;对象指针->静态数据成员名;静态成员函数静态成员函数的引入:静态成员函数属于类,不属于该类的某个对象,为该类的所有对象共享。
定义格式:static 返回类型静态成员函数名(实参表);调用格式:类名::静态成员函数名(实参表)对象.静态成员函数名(实参表)对象指针->静态成员函数名(实参表)关于静态成员函数的几点说明:1.静态成员函数主要用来静态数据成员;2.私有静态成员函数不能被类外部的的函数和对象访问;3.使用静态成员函数的原因是可以用它在建立任何对象之前调用静态成员函数对静态数据成员进行处理,而这一功能是普通成员函数不能做到的。
4.编译系统将静态成员函数限定为内部链接,与现行文件相连接的其他文件中的同名函数不会与该函数发生冲突,维护了该函数使用的安全性,这就是使用静态成员函数的另一个原因。
5.同静态数据成员一样,公有静态成员函数在类外可以使用如下格式进行调用:类名::静态成员函数名()6.静态成员函数与非静态成员函数的区别是:静态成员函数属于类,没有this指针,而非静态成员函数属于该类的某一对象,有指向该对象的this指针。
C++考试题(选择题)1、选择题1、___A__只能访问静态成员变量。
A 静态函数B 虚函数C 构造函数D 析构函数2、下列的各类函数中,__C___不是类的成员函数。
A 构造函数B 析构函数C友元函数 D 拷贝构造函数3、友元的作用_A__。
A 提高程序的运行效率B 加强类的封装性C 实现数据的隐藏性D 增加成员函数的种类4、类模板的使用实际上是将类模板实例化成一个具体的_D____。
A 类B 对象C 函数D 模板类5、下列函数中,___C__不能重载。
A 成员函数B 非成员函数C 析构函数D 构造函数6、___C__是一个在基类中说明的虚函数,它在该基类中没有定义,但要求任何派生类都必须定义自己的版本。
A 虚析构函数B虚构造函数C纯虚函数 D 静态成员函数7、__A___是istream的派生类,处理文件输入;___C__是iostream的派生类,可以同时处理文件的I/O。
A、ifstreamB、ostreamC、fstreamD、ofstream8、对于派生类的构造函数,在定义对象时构造函数的执行顺序为:先执行__A___,再执行__B___,后执行__C___。
A 成员对象的构造函数B 基类的构造函数C 派生类本身的构造函数9、局部变量可以隐藏全局变量,那么在有同名全局变量和局部变量的情形时,可以用__A___提供对全局变量的访问。
A 域运算符B 类运算符C 重载D 引用10、一个__C___允许用户为类定义一种模式,使得类中的某些数据成员及某些成员函数的返回值能取任意类型。
A 函数模板B 模板函数C 类模板D 模板类11、系统在调用重载函数时,往往根据一些条件确定哪个重载函数被调用,在下列选项中,不能作为依据的是___D__。
A 参数个数B 参数的类型C 函数名称D函数的类型12、如果一个类至少有一个纯虚函数,那么就称该类为__A___。
A 抽象类B 虚基类C 派生类D 以上都不对13、进行文件操作时需要包含__B___文件。
C++static、const和staticconst类型成员变量声明以及初始化菜鸟教程const 定义的常量在超出其作用域之后其空间会被释放,而 static 定义的静态常量在函数执行后不会释放其存储空间。
static 表示的是静态的。
类的静态成员函数、静态成员变量是和类相关的,而不是和类的具体对象相关的。
即使没有具体对象,也能调用类的静态成员函数和成员变量。
一般类的静态函数几乎就是一个全局函数,只不过它的作用域限于包含它的文件中。
在 C++ 中,static 静态成员变量不能在类的内部初始化。
在类的内部只是声明,定义必须在类定义体的外部,通常在类的实现文件中初始化,如:double Account::Rate = 2.25;static 关键字只能用于类定义体内部的声明中,定义时不能标示为static。
在 C++ 中,const 成员变量也不能在类定义处初始化,只能通过构造函数初始化列表进行,并且必须有构造函数。
const 数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。
因为类可以创建多个对象,不同的对象其const 数据成员的值可以不同。
所以不能在类的声明中初始化const 数据成员,因为类的对象没被创建时,编译器不知道const 数据成员的值是什么。
const 数据成员的初始化只能在类的构造函数的初始化列表中进行。
要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现,或者static cosnt。
class Test{ public: Test():a(0){} enum {size1=100,size2=200}; private: const int a;//只能在构造函数初始化列表中初始化 static int b;//在类的实现文件中定义并初始化conststatic int c;//与static const int c;相同。
}; int Test::b=0;//static成员变量不能在构造函数初始化列表中初始化,因为它不属于某个对象。
C++中静态成员函数访问非静态成员变量
这两天写一个简单的程序,由于程序运行占用cpu比较厉害,导致运行中界面窗口无法交互,因此想到了多线程,以前没有接触过mfc多线程,在网上看了两篇文章,觉得也不过如此,就开始动手写了,结果发现即使是看别人写很简单,自己动手也会出现很多问题,哪怕是看起来真的很简单的问题。
这里遇到的问题就是由于多线程的函数必须是static的,然后需要在里面调用non-static的函数,我就没有办法了,于是又开始网上找资料,下面就将这篇文章转贴过来,供大家学习思考:先看一个class class a { public:
static FunctionA() {
menber = 1; } private: int menber; }
编译上述代码,出错。
原因很简单大家都知道,静态成员函数不能访问非静态成员,这是因为静态函数属于类而不是属于整个对象,静态函数中的 member可能都没有分配内存。
静态成员函数没有隐含的this自变量。
所以,它就无法访问自己类的非静态成员。
(看过一篇很好的文章《浅析C++中的this指针》介绍这个方面的详细内容)那要想访问怎么办呢?地球人都知道只要将: int menber;
//change the line above to: static int menber;
但是这个方法让我们不得不将static function内用到的成员变量都变成static的了,而且static 的成员还要显式初始化,有没有更好的方法?答案是肯定的。
如下: class a { public:
static FunctionA(a* _a) {
a-> menber = 1; (window.cproArray = window.cproArray || []).push({ id: "u2280119" }); } private: int menber; }
前提是这个类要分配了内存空间。
其实这里我做的就是将一个对象指针作为静态成员函数的“this”指针,意在模仿传递非静态成员函数里this变量。