1.先看以下代码:
#include <iostream>
using namespace std;
class Base
{
static int itest;
public:
{
{
};
int Base::itest = 100;
class Derive: public Base
{
};
class Derive2: public Base
{
};
int _tmain(int argc, _TCHAR* argv[])
{
}
输出是:
102
102
我以前的理解既然Derive和Derive2是从Base派生的两个不同的类,那么他们从Base继承而来的static变量也应该是不同的两份拷贝。所以他们应该输出
101
101
而不是实际上的102.
唉,出现这样的错误看来还是自己的c++基础太差了。其实对于类的static成员变量它不单独属于任何派生类,static成员只存在一份。所有派生类包括基类均共享这唯一的一份。所以才出现了开始的输出结果。
2. 下面的程序更加证实了我的错误:
#include <iostream>
using namespace std;
class Base{
public:
};
int Base::itest = 100;
class Derive: public Base
{
};
class Derive2: public Base
{
};
int _tmain(int argc, _TCHAR* argv[])
{
}
程序输出结果表明Base和Derive以及Derive2的大小都是1. 这个结果表明Base类的static成员变量并未包含在任何一个类空间中。
3.然而对于定义static变量的类有些时候我们还是希望每个从其派生出来的类都能包含单独的一份拷贝而不是与基类和其他派生类共享。 能不能实现这样的想法呢?
答案是肯定的。
先看以下代码然后我在做解释:
#include <iostream>
using namespace std;
template< typename _class >
class Base{
public:
};
template < typename _class >
int Base< _class >::itest = 100;
class Derive: public Base<Derive>{
};
class Derive2: public Base<Derive2>{
};
int _tmain(int argc, _TCHAR* argv[])
{
}
输出:
101
101
这次的输出是101,正是我想要的结果。为什么呢?
原因是这里用到了模板,我们用不同的参数Base<Derive>、Base<Derive2>去实例化了这个模板,这就意味着Derive和Derive2派生自两个完全不同的类。因而避开了先前讨论的问题。
模板Base中定义的类型参数在Base中并没有实际的用到,他存在的唯一价值就是为我们提供了标识Base类的机会。也就是我们可以通过指定不同的类型参数而从同一个模板得到完全不同的两个类型定义。
4. 注意在类中不能对static数据成员进行初始化,要初始化的话必须在类外进行定义!注意,static数据成员不是通过类构造函数进行初始化的!如上面的代码所示:在类外定义int Person::age=20;这里前面就不要再加static了。如果类中有多个static数据成员,static数据成员初始化的次序是按照static数据成员在类中的声明次序进行初始化的,初始化了之后,就可以使用static数据成员了,我们可以通过作用域操作符从类直接调用static数据成员,或者通过对象,引用,或指向该类类型对象的指针间接调用(这种情况下static数据成员必须是public的访问权限,如果定义在private访问权限下是不行的)。
说到static数据成员,有一种情况不得不提,那就是特殊的const static成员。如上面所述,类的static成员,像普通数据成员一样,不能在类的定义体中进行初始化。只能在类外进行初始化。const int 型的static成员便可以在类定义体内部进行初始化。记住一定只能是const int型的,换成const string ,double都不行的。看下面这段代码:
#include <iostream>
#include <string>
using namespace std;
class Person
{
private:
string name;
static const int age=20;
static string address;
public:
Person(const string&nm):name(nm)
{}
static string Address()
{
return address;
}
void Print()
{
cout<<name<<" is "<<age ;
}
};
string Person::address="Beijing";
static.cpp文件
#include "stdafx.h"
#include "static.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Person person("tom");
person.Print();
cout<<" and live in "<<person.Address();
cout<<endl;
return 0;
}
只有age才能在类定义体内进行初始化,address是不行的。
5. static成员的所有者是类本身和对象,但是多有对象拥有一样的静态成员。从而在定义对象是不能通过构造函数对其进行初始化。
静态成员不能在类定义里边初始化,只能在class body外初始化。
静态成员仍然遵循public,private,protected访问准则。
静态成员函数没有this指针,它不能返回非静态成员,因为除了对象会调用它外,类本身也可以调用。
出现在类体外的函数定义不能指定关键字static;
静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
非静态成员函数可以任意地访问静态成员函数和静态数据成员;
静态成员函数不能访问非静态成员函数和非静态数据成员;