C++与Java中的static成员总结

本文详细介绍了C++和Java中的static成员,包括静态成员变量和静态成员函数。在C++中,静态成员属于整个类,通过类名访问,静态函数不能是虚函数。而在Java中,静态变量在类加载时初始化,被所有对象共享,静态方法不能访问非静态成员,主要适用于共享数据和常量值。总结指出,无论在C++还是Java中,static成员都属于类,静态函数不能调用非静态成员,主要是由于this指针的限制。

简述

在结构化程序设计中,内存中数据的共享是通过参数, 全局变量实现的;
在面向对象程序设计中函数与数据成员封装在一起, 数据共享通过类内部数据成员之间的相互访问, 外部对象则通过静态成员(即static成员)来共享数据;
接下来通过面向对象叙述static特性

C++中的static

静态成员
使用关键字static修饰的函数/数据成员, 静态成员属于整个类, 由同一个类的所有对象所拥有,共享; 一般通过类名进行访问: 类名::标识符 ;
注: 在类中定义静态数据成员, 仅仅是对静态数据成员进行引用性声明, 必须在类外使用类名限定定义性声明(即真正的声明),这时才能进行初始化

#include<iostream>
using namespace std;
class A{
    public:
        static int count;
        A(){
            ++count; 
            cout<<"构造函数"<<endl; 
        }
        A(A const& a){
            ++count; 
            cout<<"复制构造函数"<<endl;   
        }
        ~A(){cout<<"析构函数"<<endl;
            count--; 
        }
        static int show(){
            return count; //静态成员函数可以直接访问该类的静态数据成员,访问费静态数据成员只能通过对象名
        } 

};
int A::count=0; 
void f(){//顺带测试一下静态生存期
    static int j=0; 
    j+=2;
    int i=2;
    cout<<i<<" static j="<<j<<endl;
    i+=2; 
}
int main(){
    f();
    cout<<"A对象个数"<<A::show()<<endl;//还没有构造对象的时候,count数为0
    A a;
    A b=a;//发生复制构造 
    A c(b);
    A d;
    cout<<"A对象个数"<<A::count<<endl; //此时count数为4
    cout<<endl;
    f(); 
    return 0; 
} 

此处做着重说明: 静态函数不能是虚函数, 虚函数用于动态绑定(通过虚表的索引值进行函数地址的查找, 索引值必须用到this, 所以静态函数函数不能作为虚函数)
为何static成员函数不能为virtual
1. static成员不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义的。
2. 静态与非静态成员函数之间有一个主要的区别。那就是静态成员函数没有this指针。
虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,因为它是类的一个成员,并且vptr指向保存虚函数地址的vtable.
对于静态成员函数,它没有this指针,所以无法访问vptr. 这就是为何static函数不能为virtual.
虚函数的调用关系:this -> vptr -> vtable ->virtual function

第二点: 对const成员函数设置为静态没有任何意义, const只是对函数的this指针进行限制, 而静态函数没有this指针

使用普通指针指向类的静态成员

#include <iostream> 
using namespace std;
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0){
         count++; 
         width = a;
         height = b;
      }
    int area(){
         cout << "Parent class area :" <<endl;
         return (width * height / 2);
      }
    static int count; //只能进行声明 
};
int Shape::count=0;//查看总共生成的对象总数
int main( )
{
    cout<<"count="<<Shape::count<<endl;
    Shape s;
    Shape s1(2,3);
    cout<<s.area()<<endl;
    cout<<s1.area()<<endl;
    int *p=&Shape::count;
//  int Shape::*p=&Shape::count; //这种做法将会报错([Error] cannot convert 'int*' to 'int Shape::*' in initialization),指针的转化的过程中 涉及到this,p指针不依赖于对象属于static的范围,所以要用普通指针来进行操作
    cout<< "count"<<*p<<endl; 
    cout<<"count="<<Shape::count<<endl;
   return 0;
}

Java中的static

Java中的静态变量(类变量): static修饰, 主要用于修饰类成员方法, 加载优先于对象初始化(static成员在类被加载的时候就被加载了, 加载static成员会优先于), 静态代码块优先于构造方法执行, 被所有对象共享

  • 整个类中只有一个值
  • 类初始化的同时就被赋值
  • 适用于所有类对象都具有的相同属性,经常需要共享的数据, 系统中的常量值
  • 引用格式: 类名.变量名(或者静态函数名)

静态方法: 类方法,属于当前类, 调用直接类名.静态方法(), 只能是外部静态数据成员, 静态方法中不可出现this关键字; 静态方法中不能访问非静态成员(包含属性, this,super, 非静态方法); 原因在于当前对象未构造, 无属性,this,super存在, 但是反之即可(对象都创建了, 肯定能访问)
例:

public class test{
    public static void main(String[] args){
        System.out.println(A.show());
        A a1=new A();
        A a2=new A();
        A a3=new A();
        System.out.println(A.show());
    }
}
class A{
        public static int i=0;
        public A(){i++; System.out.println("构造方法");}
        public static int show(){return i;}
}
//结果将显示0 3,表示构造3个对象

静态方法调用非静态时引发的错误

public class test{
    public void info(){
        System.out.println("一般方法");
    }
    public static void main(String[] args){
        info();
    }
}

上述操作将出现错误静态上下文引用非静态变量, main()方法为static, 当main方法初始化的时候, 对象还未创建, 调用info的对象是this, this还未被创建,对上述操作有如下改进

public static void main(String[] args){
    new test().info();
}

注: 当涉及到super时, 效果与this一致;

java接口中不能有静态代码块(静态方法)
接口: 规定方法原型(方法名,参数列表,返回类型),不规定方法主体(静态代码块属于方法主体), 只具有方法的声明;
也包含基本数据类型的数据成员,但是都默认为static和final;
需要注意的是: java8中引入接口可以具有默认方法, 子类可以重写接口的方法

总结

C++与Java中的static用法具有区别, 但是核心都是static只属于类, 静态函数不能调用非静态变量(包含this,super, 一般成员函数,成员变量), 最主要的原因还是在于this的隐藏, 大多数的出现的静态调用非静态主要在于this,super以及在对象还未产生就调用对象的函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值