静态属性和静态方法2
潜规则:
- 静态成员是所有对象共享的,所以不能在静态方法里访问非静态的元素。
- 非静态方法可以访问类的静态成员,也可以访问类的非静态成员。
为什么呢?
回顾下:this指针是类的一个自动生成、自动隐藏的私有成员,它存在于类的非静态成员函数中,指向被调用函数所在的对象的地址。当一个对象被创建时,该对象的 this指针就自动指向对象数据的首地址。我们从一个比较有特色的例子来体会 this指针的工作原理:特色例子.txt。
#include<iostream> class Point { private: int x, y; public: Point(int a, int b) { x = a; y = b; } void MovePoint( int a, int b) { x = a; y = b; } void print() { std::cout << "x=" << x << "y=" << y << endl; } }; int main() { Point point1(10, 10); point1.MovePoint(2, 2); point1.print(); return 0; } // 当对象point1调用MovePoint(2,2)函数时,即将point1对象的地址传递给了this指针。 // MovePoint函数的原型事实上应该是 void MovePoint( Point *this, int a, int b); // 第一个参数是指向该类对象的一个指针,我们在定义成员函数时没看见是因为这个参数在类中是隐含的。 // 这样point1的地址传递给了this,所以在MovePoint函数中便可以显式的写成:void MovePoint(int a, int b) { this->x = a; this->y = b;} // 即可以知道,point1调用该函数后,也就是point1的数据成员被调用并更新了值。
在任何一个方法里都可以使用 this 指针。从本质上讲,C++中的对象其实是一种特殊的结构 -- 除了变量,还包含着一些函数的特殊结构。 在程序运行时,对象的属性(变量)和方法(函数)都是保存在内存里,这就意味着它们各自都有与之相关联的地址。 这些地址都可以通过指针来访问,而 this指针毋庸置疑是保存着对象本身的地址。
每当我们调用一个方法的时候,this指针都会随着你提供的输入参数被秘密的传递给那个方法。 正是因为如此,我们才能在方法里像使用一个局部变量那样使用 this指针。 因为静态方法不是属于某个特定的对象,而是由全体对象共享的,这就意味着它们无法访问 this指针。所以,我们才无法在静态方法里访问非静态的类成员。
另外需要注意:
- 在使用静态属性的时候,千万不要忘记为它们分配内存。具体做法很简单,只要在类声明的外部对静态属性做出声明(就像声明一个变量那样)即可。
#include <iostream> #include <string> class Pet { public: Pet(std::string theName); ~Pet(); static int getCount(); protected: std::string name; private: static int count;//声明了count静态属性 }; class Dog : public Pet { public: Dog(std::string theName); }; class Cat : public Pet { public: Cat(std::string theName); }; int Pet::count = 0; // 注意这一句,他起码做了两件事:创建内存区域并对其初始化 Pet::Pet(std::string theName) { name = theName; count++; std::cout << "一只宠物出生了,名字叫做: " << name << "\n"; } Pet::~Pet() { count--; std::cout << name << "挂掉了\n"; } int Pet::getCount() { return count; } Dog::Dog(std::string theName) : Pet(theName) { std::cout << "this:" << this << "\n"; } Cat::Cat(std::string theName) : Pet(theName) { } int main() { Dog dog("Tom"); Cat cat("Jerry"); std::cout << "dog:" << &dog << "\n"; std::cout << "\n已经诞生了" << Pet::getCount() << "只宠物!\n\n"; Dog dog_2("Tom_2"); Cat cat_2("Jerry_2"); std::cout << "\n现在呢,已经诞生了" << Pet::getCount() << "只宠物!\n\n"; std::cout << "\n现在还剩下 " << Pet::getCount() << " 只宠物!\n\n"; return 0; }
- 静态方法也可以使用一个普通方法的调用语法来调用,但建议不要这么做,那会让代码变得更糟糕!
-
请坚持使用:ClassName::methodName();
-
请不要使用:objectName.methodName();