静态属性和静态方法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();

posted @ 2019-02-19 09:59  耐烦不急  阅读(224)  评论(0编辑  收藏  举报