C++_静态成员

静态数据成员

为什么要引入静态数据成员:主要原因是为了取代全局变量,让类的所有对象共享数据。

什么时候使用静态数据成员:定义类的各个对象公有的数据,如统计总数,平均数

优点:可以节省内存

类中的静态变量在内存中只存储一次,供所有对象所共有的,一旦一个对象改变其值,其他对象可以直接使用改变的值,这样可以提高效率和节省内存空间。

缺点:

由于静态变量时是类的多个对象共享。则在多线程的情况下,访问静态变量我们需要加一些异步机制,防止多个线程同时修改静态变量。

语法:

定义:static + 普通数据成员定义

初始化位置:必须在类外初始化,主函数前,而不能在类中进行初始化

注意:不能在类的初始化(在.h文件中)中对静态变量进行初始化,这样会导致重复定义

初始化方式:类型 类名::变量 = 值;------注意这时,前面不能加static

使用:

类外使用:

访问规则:public

使用方式:类对象名.静态数据成员名 或 类类型名::静态数据成员名

静态成员函数

为什么要引入静态数据成员:主要原因是为了取代全局函数,能在调用构造函数前(未初始化类之前)调用,通常CALLBACK函数中会用得到。

什么时候使用静态数据成员:

(1) 为了访问全局变量或类的静态数据成员

(2) 要调用一个函数,该函数是在构造对象之前使用,但是不能使用全局函数(不符合OO实现),而且类中非静态函数的调用需要使用对象,这时候需要使用静态成员函数。

语法:

定义:static + 普通成员函数定义

定义位置:可以在类内,也可以自类外。类外定义是不加static

使用:

类外使用:

访问规则:public

使用方式:类名::静态公有成员函数名(实参表);

注意:和普通的成员变量一样,如果是私有或受保护的,不能在类外直接使用

类中使用:

访问规则:public/protected/private(可以是任意方式定义)

使用方式:直接使用静态成员函数

性质:

1、没有this指针,不可以直接访问类中非非静态成员函数,常常用于访问类的静态数据和静态成员函数。

2、只属于一个类,可以再多个对象间共享。

3、一般情况下,静态成员函数不访问非静态成员函数,如果确实需要,则需要传入参数通过对象名访问。

4、静态成员函数不可以同时声明为virtual、const、volatile函数。

5、静态成员函数不能是虚函数

举例:

#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;        //10

test::num = 20;

cout<<test::num<<endl;        //20

cout<<test::Getnum()<<endl;   //35

cout<<a.Getnum()<<endl;       //50

system("pause");

return 0;

}

通过上例可知:  x+=5;   // 这行代码是错误的

静态函数成员必须通过对象名来访问非静态数据成员。

另外,静态成员函数在类外实现时候无须加static关键字,否则是错误的。

若在类的体外来实现上述的那个静态成员函数,不能加static关键字,这样写就可以了:

int test::Getnum()

{

.........

}

1、static成员的所有者是类本身和对象,但是多有对象拥有一样的静态成员。从而在定义对象是不能通过构造函数对其进行初始化。

2、静态成员不能在类定义里边初始化,只能在class body外初始化。

3、静态成员仍然遵循public,private,protected访问准则。

4、静态成员函数没有this指针,它不能返回非静态成员,因为除了对象会调用它外,类本身也可以调用。

[cpp] view
plain
copy

  1. #include<iostream>
  2. using namespace std;
  3. class A
  4. {
  5. private:
  6. int i;
  7. static int j;
  8. public:
  9. A(int i=1)
  10. {
  11. this->i=i;
  12. }
  13. static void show();
  14. void show(const A&a);
  15. };
  16. int A::j=0; //类外初始化静态变量时,不要加static
  17. void A::show()//类外定义函数体时,不要加static ----静态函数访问静态成员
  18. {
  19. cout<<j<<endl;
  20. }
  21. void A::show(const A&a)//静态函数访问非静态成员,必须加参数
  22. {
  23. cout<<a.i<<endl;
  24. cout<<j<<endl;
  25. }
  26. void main()
  27. {
  28. A a;
  29. a.show();
  30. a.show(a);
  31. system("pause");
  32. }

注意:

1、类的静态成员函数不能访问非静态成员,但是非静态成员可以访问静态成员。

2、出现在类体外的函数定义不能指定关键字static;

3、静态成员之间可以相互访问,即静态成员函数访问静态数据成员和访问静态成员函数;

4、非静态成员函数可以任意地访问静态成员函数和静态数据成员;

5、静态成员函数不能访问非静态成员函数和非静态数据成员;

6、调用静态成员函数,可以用对象调用,也可以通过类调用

说明:

1、static与const的对比

变量的对比:

static:是为限定变量的作用域的,值是可以改变的

const:是表示变量是常量,是不可变的,提高程序健壮性。

函数的对比:

static:

修饰C中的函数:是为了限定作用域仅在本文件,其他文件不可用

修饰C++中的函数:是为了在对象创建之前做一些操作

const:

表示函数中的变量不可修改。

在类中声明static变量或者函数时,初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员,这样就出现以下作用:

(1)类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致 了它仅能访问类的静态数据和静态成员函数。

(2)不能将静态成员函数定义为虚函数。

(3)由于静态成员声明于类中,操作于其外,所以对其取地址操作,就多少有些特殊 ,变量地址是指向其数据类型的指针 ,函数地址类型是一个“nonmember函数指针”。

(4)由于静态成员函数没有this指针,所以就差不多等同于nonmember函数,结果就 产生了一个意想不到的好处:成为一个callback函数,使得我们得以将C++和C-based X W indow系统结合,同时也成功的应用于线程函数身上。 (这条没遇见过)

(5)static并没有增加程序的时空开销,相反她还缩短了子类对父类静态成员的访问 时间,节省了子类的内存空间。

(6)静态数据成员在<定义或说明>时前面加关键字static。

(7)静态数据成员是静态存储的,所以必须对它进行初始化。 (程序员手动初始化,否则编译时一般不会报错,但是在Link时会报错误)

(8)静态成员初始化与一般数据成员初始化不同:

初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆;

初始化时不加该成员的访问权限控制符private,public等;

初始化时使用作用域运算符来标明它所属类;

所以我们得出静态数据成员初始化的格式:

<数据类型><类名>::<静态数据成员名>=<值>

(9)为了防止父类的影响,可以在子类定义一个与父类相同的静态变量,以屏蔽父类的影响。这里有一点需要注意:我们说静态成员为父类和子类共享,但我们有重复定义了静态成员,这会不会引起错误呢?不会,我们的编译器采用了一种绝妙的手法:name-mangling 用以生成唯一的标志

时间: 2024-10-13 00:11:14

C++_静态成员的相关文章

C++之基础知识20170830

/******************************************************************************************************************/ 一.C++类的引入 与C相比, 1.编译使用g++代替 gcc,执行在linux中还是一样的 2.c++里面也有struct并对其进行了扩展,struct中的函数可以直接使用其成员,并可在struct中直接实现, 例: struct person { char *n

面向对象程序设计-C++_课时28静态对象_课时29静态成员

Static in C++ Two basic meanings Static Storage --allocated once at a fixed address Visibility of a name --internal linkage Don't use static except inside functions and classes. Uses of "static" in C++ Static free functions----deprecated弃用 Stati

尚学堂_java300集笔记_手写服务器

195.httpserver_准备_Socket入门 public class Server { private ServerSocket server; public static void main(String[] args) { Server server = new Server(); server.start(); } public void start() { try { server = new ServerSocket(8080); String msg = null; thi

接口和抽象类:Interface、abstract _【转】

一.接口 接口是C#中很常见的工具,概念什么的就不说了,这里讲几个值得注意的小地方: 1.接口内部只能有函数.属性和事件的声明: interface IParent { void Show(); string Type { get; set; } event AddChildren Add; } 在接口中声明的成员都不需要访问修饰符(public,private等),因为接口成员的权限默认都是public,另外值得注意的是接口中之所以能够声明事件是因为事件就是委托的特殊属性. 接口不能是静态的,

黑马程序员_JavaSE学习总结第27天_反射 &amp; 设计模式 &amp; JDK5、7、8新特性

------- android培训.java培训.期待与您交流! ----------  27.01  反射_类的加载概述和加载时机 类的加载:当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 加载:就是指将class文件读入内存,并为之创建一个Class对象.任何类被使用时系统都会建立一个Class对象. 连接 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数

黑马程序员_毕向东_Java基础视频教程_Java基础学习知识点总结

黑马程序员_毕向东_Java基础视频教程 Java基础学习知识点总结 2016年01月06日  day01 一.基础知识:软件开发 1.什么是软件?软件:一系列按照特定顺序组织的计算机数据和指令的集合. 2.常见的软件:系统软件:如:DOS,Windows,Linux等.应用软件:如:扫雷,迅雷,QQ等. 3.什么是开发?制作软件. 二.基础知识:人机交互方式 4.软件的出现实现了人与计算机之间的更好的交互. 5.交互方式:图形化界面:这种方式简单直观,使用者易于接受,容易上手操作.命令行方式:

C++ Primer 学习笔记_17_类与数据抽象(3)_类作用域

C++ Primer 学习笔记_17_类与数据抽象(3)_类作用域 引言: 每个类都定义了自己的新作用域与唯一的类型.即使两个类具有完全相同的成员列表,它们也是不同的类型.每个类的成员不同与任何其他类(或任何其他作用域)的成员. 一.类作用域中的名字查找 1)首先,在使用该名字的块中查找名字的声明.只考虑在该项使用之前声明的名字. 2)如果在1)中找不到,则在包围的作用域中查找. 如果找不到任何声明,则出错. 类的定义实际上是在两个阶段中处理: 1)首先,编译器声明: 2)只有在所有成员出现之后

IOS_多线程_售票

H:/1007/01_多线程_大任务_MainViewController.m // MainViewController.m // 多线程-01.大任务 // Created by apple on 13-10-7. #import "MainViewController.h" @interface MainViewController () @property (weak, nonatomic) UIImageView *imageView; @end @implementatio

javase(5)_面向对象

一.概述 1.面向对象是一种思想,让我们由执行者变成指挥者,执行者是面向过程,指挥者是面向对象.例如人开冰箱门,开冰箱门这个动作应该属于门而不是人,冰箱自己最清楚门应该怎么开,人只是调用了冰箱的这个动作. 2.面向对象开发例子 1.电脑坏了,找个修电脑的人,我们调用修电脑这个人修电脑的功能即可,自己不需要知道具体怎么修;2.公司老板找人完成软件开发... 3.开发的时候先想是否java已经实现了这个功能,找这个对象拿过来用,如果没有,自己造一个对象来用,自己能用别人也能用,开发就是找对象,找不到