类的静态成员

有的时候类需要它的一些成员与类本身直接相关,而不是与类的各个对象保持关联。

声明静态成员

我们通过在成员的声明之前加上关键字static使得其与类关联在一起,和其他成员一样,静态成员可以使public得或private的。静态数据成员的类型可以使常量、引用、指针、类类型等

举个例子,我们定义一个类,用它表示银行的账户记录:

class Account{

public:
    void calculate() {amount+=amount*interestRate;}
    static double rate() {return interestRate;}
    static void rate(double);
private:
    std::string owner;
    double amount;
    static double interestRate;
    static double initRate();
};

类的静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据。因此,每个Account对象将包含两个数据成员:owner和amount。只存在一个interestRate对象而且它被所有所有Account对象共享。

类似的,静态成员函数也不与任何对象绑定在一起,它们不包含this指针。作为结果,静态成员函数不能声明成const的,而且我们也不能在static函数体内使用this指针,这一限制既适用于this的显式使用,也对调用非静态成员的隐式使用有效。静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。静态成员函数不可以同时声明为   virtual、const、volatile函数   。

 class   base{
              virtual   static   void   func1();//错误
              static   void   func2()   const;//错误
              static   void   func3()   volatile;//错误
        };   

使用类的静态成员


我们使用作用域运算符直接访问静态成员:

double r;

r=Account::rate();   //使用作用域运算符访问静态成员

虽然静态成员不属于类的某个对象,但是我们仍然可以使用类的对象、引用或者指针类访问静态成员:

Account ac1;

Account *ac2=&ac1;

//调用静态成员函数rate的等价形式

r=ac1.rate();   //通过Account的对象或引用

r=ac2->rate();   //通过指向Account对象的指针

成员函数不要通过作用域运算符就能直接使用静态成员。

class Account{

public:

  void calculate() {amount+=amount*interestRate;}

private:

  static double interestRate;

};

静态数据成员函数

静态成员函数:静态成员函数一般只能访问静态成员变量,如果要访问非静态成员变量的话,只能访问某一个对象的非静态成员变量和静态成员函数。可以传一个对象的指针,引用等参数给这个静态成员函数。

 class   a   {
public:
    a():m_ia(123)   {}
    int   getia()   {   return   m_ia;   }
    static   int   f(a &aa)   {   return   aa.getia();   }
private:
    int   m_ia;
};  

void   main()
{
    a   aa;
    cout<<a::f(aa);
}  

静态成员函数中是不能调用非静态成员的,包括非静态成员函数和非静态成员变量。那么在非静态成员函数中是否可以调用静态成员函数呢?答案是肯定的,因为静 态成员函数属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员函数的。其实,我们也可以以一个内存模型这个角度来考 虑,也就是说,无论采取什么样的操作,程序代码都是在内存中运行的,只有在内存中占有了一席之地,我们才能访问它。如果一个成员函数或成员变量还没有在内 存中产生,结果是无法访问它的。所有静态成员函数只能访问静态成员变量。

使用static关键字声明的函数成员是静态的,静态成员函数同样也属于整个类,由同一个类的所有对象共同维护,为这些对象所共享.   
      作为成员函数,它的访问属性可以受到类的严格控制,对于公有的静态函数成员函数,可以通过类名或对象名来调用,但一般情况下建议用对象名来引用静态函数成员.注意,一般的成员函数只能通过对象名来调用.   
        由于一个类的静态成员函数只有一个拷贝,因此它访问对象的数据和函数时受到了限制.静态成员函数可以直接访问该类的静态数据成员.而访问非静态数据成员, 必须通过参数传递方式得到对象名,然后通过对象名来访问.可以看到,通过静态函数成员访问非静态成员使相当麻烦的,一般的使用中,它主要用来访问全局变量 或同一个类中的静态数据成员,特别是和后者一起使用,达到对同一个类中对象之间共享的数据进行维护的目的.   
        构造函数和析构函数不可以定义为static,构造函数要给每一个对象一个this指针如果可以是静态的,它如何构造和访问this指针?
明显是不可以的!

静态成员变量一般要在.cpp文件里进行定义:

  double Account::_interestRate = 0.0589;

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

const string str = "liangxueliang";
    Account *Acc = new Account(222222,str);
    Acc->getRate();
    Account::getRate();

定义静态数据成员 

和其他的成员函数一样,我们既可以在类的内部也可以在类的外部定义静态成员函数。当在类的外部定义静态成员时,不能重复static关键字,该关键字只出现在类内部的声明语句:

void Account::rate(double newRate)

{
  interestRate=newRate;

}

和类的所有成员一样,当我们指向类外部的静态成员时,必须指明成员所属的类名。static关键字则只出现在类内部的声明语句中

因为静态数据成员不属于类的任何一个对象,所以它们并不是在创建类的对象时被定义的。这意味着它们不是由类的构造函数初始化的。而且一般来说,我们不能在类的内部初始化静态数据成员。相反的,必须在类的外部定义和初始化每个静态成员。和其他对象一样,一个静态数据成员只能定义一次。

类似于全局变量,静态数据成员定义在任何函数之外,因此一旦它被定义,就将一直存在于程序的整个生命周期中。

我们定义静态数据成员的方式和在类的外部定义成员函数差不多。我们需要指定对象的类型名,然后是类名、作用域运算符以及成员自己的名字:

//定义并初始化一个静态成员

double Account::interestRate=initRate();

这条语句定义了名为interestRate的对象,该对象是类Account的静态成员,其类型是double。从类名开始,这条定义语句的剩余部分就都位于类的作用域之内了。因此,我们可以直接使用initRate函数。注意,虽然initRate是私有的,我们也能使用它初始化interestRate。和其他成员的定义一样,interestRate的定义也可以访问类的私有成员。

要想确保对象只定义一次,最好的办法是把静态数据成员的定义与其他非内联函数的定义放在同一文件中。

静态成员的类内初始化

通常情况下,类的静态成员不应该在类的内部初始化。然而,我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr。初始值必须是常量表达式,因为这些成员本身就是常量表达式,所以它们能用在所有适用于常量表达式的地方。例如,我们可以用一个初始化了的静态数据成员执行数组成员的维度:

class Account{
public:
    static double rate() { return interestRate;}
    static void rate(double);
private:
    static constexpr int period=30;
    double daily_tbl[period]; //period是常量表达式
};

如果在类的内部提供了一个初始值,则成员的定义不能再指定一个初始值了:

//一个不带初始值的静态成员的定义

constexpr int Account::period;  //初始值在类的定义内提供

即使一个常量静态数据成员在类内部被初始化了,通常情况下也应该在类的外部定义一下该成员。

静态成员能用于某些场景,而普遍成员不能

如我们所见,静态成员独立于任何对象。因为,在某些非静态数据成员可能非法的场合,静态 成员却可以正常地使用。举个例子,静态数据成员可以是不完全类型。特别地,静态数据成员的类型可以就是它所属的类类型。而非静态数据成员则受到限制,只能声明成它所属类的指针或引用。

class Bar{
public:
    //......
private:
    static Bar mem1;  //正确:静态成员可以是不完全类型
    Bar *mem2;         //正确:指针成员可以使不完全类型
    Bar mem3;         //错误:数据成员必须是完全类型
};

静态成员和普通成员的另一个区别是我们可以使用静态成员作为默认实参:

class Screen{
public:
    //bkground 不是一个在类中稍后定义的静态成员
    Screen &clear(char =bkground);
private:
    static const char bkground;
};

非静态数据成员不能作为默认实参,因为它的值本身属于对象的一部分,这么做的结果是无法真正提供一个对象以从中获取成员的值,最终引发错误。

类的静态成员,布布扣,bubuko.com

时间: 2024-08-04 14:43:46

类的静态成员的相关文章

C++ 类的静态成员详细讲解

在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存. 静态成员的定义或声明要加个关键static.静态成员可以是Public,Private,Protected:Public的静态成员可以通过双冒号来使用即<类名>::<静态成员名>. 在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变

枚举(enum)与类的静态成员(static)

枚举(ENUM)与类的静态成员(static) 枚举表示可以计数的一种类型 Gender.java public enum Gender { male, Female, } Person.java public class Person { String name; int age; Gender gender; static String nation; /** * display()显示方法 * */ void display() { System.out.println(String.fo

第25课 类的静态成员变量

1. 成员变量的回顾 (1)通过对象名能够访问public成员变量 (2)每个对象的成员变量都是专属的 (3)成员变量不能在对象之间共享 2. 静态成员变量 (1)C++中的静态成员变量 ①静态成员变量属于整个类所有 ②静态成员函变量的生命期不依赖于任何对象 ③可以通过对象名,也可以通过类名直接访问公有静态成员变量 ④所有对象共享类的静态成员变量 (2)静态成员变量的特性 ①在定义时直接通过static关键字修饰 ②静态成员变量在程序内部位于全局数据区,所以需要类外为其单独分配空间.(因为new

[email&#160;protected]类的静态成员变量和静态成员函数

参考: http://blog.csdn.net/morewindows/article/details/6721430 http://www.cnblogs.com/lzjsky/archive/2011/01/24/1943199.html 分析Qt程序时,碰到下面代码. QString str = QString("QFrame#avatar{border-image:url(%1.jpg)}").arg( QString::number(i) );   静态成员变量 静态成员函

C++面向对象学习-类的静态成员

1 静态数据成员 2 1,sizeof 运算符不会计算静态成员. 3 4 2,对静态成员数据初始化的顺序为它们在类体外声明的顺序. 5 6 3,静态数据成员被类的所有对象所共享,包括该类的派生类对象. 7 8 4,静态成员数据也可以分为公有的.私有的和受保护的静态成员. 9 对公有静态成员,即可以通过类的对象进行访问,也可以通过类名直接访问. 10 私有的和保护的静态成员数据则只能被该类的公有成员函数访问. 11 12 5,在创建任何对象之前,类的静态成员数据已经存在并可以引用. 13 14 6

分析java类的静态成员变量初始化先于非静态成员变量

分析java类的静态成员变量初始化先于非静态成员变量 依上图中当class字节码文件被jvm虚拟机加载到内存中依次经过 连接 验证:对字节码进行验证 准备:给静态变量分配内存并赋予变量类型各自的默认值(注:基本类型为0或false,对象为null,static final修饰的常量直接赋予相应的值) 解析:类中符号引用转换成直接引用 初始化:为类的静态变量/静态语句块初始化相应的值 而类的初始化契机是:类在被第一次主动使用的情况下,主动使用包括以下6中情况: 使用new关键字实例化对象时. 调用

类之静态成员以及常对象、常成员

一.静态成员:static修饰,每个类只有一份拷贝,为所有该类的对象所共用. 1.静态数据成员: 类内声明.类外初始化.和全局变量一样,在数据段里分配内存. eg: class A{ static int co; }; int A::co=0; 2.静态成员函数: 1).静态成员函数专门用来存取类的静态成员,不可访问非静态成员,没有this指针.由static在类内声明,可以在类外定义,此时不需要static作为前缀. eg: class A{ static int co; static int

面向对象课后深入学习(C++ 类的静态成员详细讲解)

今天在刚申请了博客,一下午都在写那个随笔,所以说好的来看c++的也放在了最后,下星期就考试了,这个类的静态成员是我不是很懂的,在网上 看到一片很详细的博客考下来回去慢慢看. 在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用.所以在所有对象中都可以共享它.使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存. 静态成员的定义或声明要加个关键static.静态成员可以通过双冒号来使用即<类名>::<静态成员名>.

5、类的静态成员

问题: 如何统计对象的个数呢?     (1)普通的成员变量?不行,因为对于普通的成员变量,对象都有各自的成员变量,他们都是相互独立的,所以并不能实现对象个数的统计     (2)全局变量:可以,但是一般来说,我们都是尽量避免全局变量(周期长,占内存,出错的时候, 不易查找),     (3)类的静态成员变量和静态成员函数: YES 静态成员:     (1)静态成员是属于整个类所有的,不依赖于任何对象,依赖于类的存在(所以才可以通过类名直接访问静态成员变量和静态成员函数),对象的创建和销毁都不