静态成员函数与普通成员函数的区别,什么时候用静态函数比较好?

成员函数(也称为非静态成员函数)和静态成员函数之间有一些关键的区别:

关联对象:

  • 成员函数:每个成员函数在调用时都会关联到一个特定的对象实例。在成员函数内部,可以使用this指针来访问对象的成员变量。obj.func()这种调用可以理解为:myClass::func(&obj)
  • 静态成员函数:静态成员函数不与特定的对象实例关联。它们没有隐含的this指针,因此无法直接访问静态成员变量。静态成员函数的调用方式更类似于普通函数调用,而不需要通过对象来调用。

访问权限:

  • 成员函数:可以访问类中的所有成员,包括私有成员。
  • 静态成员函数:可以访问类的静态成员(包括静态变量和静态函数),但不能直接访问非静态成员,因为它们没有关联的对象实例。

调用方式:

  • 成员函数:需要通过对象来调用,使用成员运算符 . ->。成员函数调用时会自动传递调用对象给this指针。
  • 静态成员函数:可以通过类名直接调用,也可以通过对象调用。但无论哪种方式,静态成员函数都不会自动接收 this 指针,因为它们没有对象关联。

存储方式:

  • 成员函数:每个对象实例并不存储成员函数的代码,只存储成员变量。成员函数的代码只有一份,存储在可执行代码段中。
  • 静态成员函数:同样地,静态成员函数的代码只有一份,存储在可执行代码段中。静态成员变量也只有一份,存储在全局数据区域。

调用约定:

  • 成员函数:因为成员函数关联到对象实例,调用时会在运行时动态解析正确的函数。这可能会带来轻微的运行时开销。
  • 静态成员函数:由于它们不与对象实例关联,调用静态成员函数没有对象查找开销,更类似于普通函数调用。

总之,成员函数主要用于操作对象实例的状态,而静态成员函数则更像是与类本身相关的功能函数。静态成员函数不依赖于对象实例,因此它们在某些情况下更具有通用性和效率。


在什么情况下应该把一个函数设计为静态成员函数?

核心思想:就是一个普通函数,但是与这个类非常相关,应该放在这个类中,但是它不需要这个类的实例的信息,可以理解为仅仅是给这个函数一个作用域。

在C++中,将函数设计为静态成员函数(静态方法)通常是出于以下一些情况或考虑:

  • 无需访问实例数据: 静态成员函数不依赖于类的实例,因此它们无法访问非静态成员变量和其他实例相关的数据。如果函数的实现不需要访问类的实例数据,那么它可以被设计为静态成员函数。

  • 与类相关但不需要实例: 有时候,你可能希望在类的上下文中执行某些操作,但这些操作不需要实例的状态。例如,你可以将一个工具函数设计为静态成员函数,用于在类的范围内执行某个通用操作。

    class Shape 
    {
    public:
    	// 构造函数等其他成员...
    
        static double getTotalArea() 
        {
            double totalArea = 0.0;
            for (const auto& shape : allShapes) 
            {
                totalArea += shape->calculateArea();
            }
            return totalArea;
        }
    
    	virtual double calculateArea() const = 0; // 抽象函数
    private:
    	static std::vector<Shape*> allShapes; // 保存所有已创建的图形指针
    };
    std::vector<Shape*> Shape::allShapes; // 初始化静态成员
    
    class Circle : public Shape 
    {
    public:
    	// 构造函数等其他成员...
    
    	double calculateArea() const override 
    	{
        	// 计算圆的面积
    	}
    };
    class Rectangle : public Shape 
    {
    public:
        // 构造函数等其他成员...
    
        double calculateArea() const override 
        {
            // 计算矩形的面积
        }
    };
    
    int main() 
    {
        Circle circle;
        Rectangle rectangle;
    
        // 将图形对象添加到allShapes中....
    
        double totalArea = Shape::getTotalArea(); // 调用静态成员函数
        std::cout << "Total area of all shapes: " << totalArea << std::endl;
    
        return 0;
    }
    
  • 工具函数或算法: 如果函数执行的是某种与类相关的工具函数、算法或静态计算,它可能不需要直接操作类的实例数据。这种情况下,静态成员函数可以提供一种清晰的方式来组织代码。

  • 避免实例化: 有时,你可能想在不实例化类的情况下使用类的功能。这时,静态成员函数可以提供一种简单的方法,因为它们不需要类的实例来调用。

    class Point 
    {
    public:
        Point(double x, double y) : x(x), y(y) {}
    	// 计算点到点的距离,与点非常相关,放这里仅仅是给它加个作用域罢了  放类外也无所谓 但是不是很面向对象咯~
        static double calculateDistance(const Point& p1, const Point& p2) 
        {
            double dx = p1.x - p2.x;
            double dy = p1.y - p2.y;
            return std::sqrt(dx * dx + dy * dy);
        }
    
    private:
        double x, y;
    };
    
    int main() 
    {
        Point p1(0.0, 0.0);
        Point p2(3.0, 4.0);
    
        double distance = Point::calculateDistance(p1, p2); // 调用静态成员函数
        std::cout << "Distance between points: " << distance << std::endl;
    
        return 0;
    }	
    
  • 访问限制: 静态成员函数只能访问类的静态成员变量和其他静态成员函数,这有助于限制对类的特定部分的访问。如果你想要提供一个只能操作静态数据的函数,静态成员函数可以派上用场。

  • 假设我们正在编写一个简单的图形库,有个Shape类,其中包含一些静态数据,如图形的数量。我们想要提供一个只读的函数来获取图形的总数量,但不希望函数能够修改单个图形的属性。在这种情况下,你可以使用静态成员函数来实现只读的总图形数量计算,同时限制它只能访问静态成员变量。

    class Shape 
    {
    public:
        Shape() 
        {
            totalShapes++; // 每次创建图形对象时递增计数
        }
    
        static int getTotalShapes() 
        {
            return totalShapes;
        }
    
    private:
        static int totalShapes; // 所有图形的总数
    };
    
    int Shape::totalShapes = 0; // 初始化静态成员
    
    int main() 
    {
        Shape shape1;
        Shape shape2;
        Shape shape3;
    
        int totalShapes = Shape::getTotalShapes(); // 调用静态成员函数
        std::cout << "Total number of shapes: " << totalShapes << std::endl;
    
        return 0;
    }
    

总而言之言而总之,静态函数和静态变量并不影响这个类的功能和含义,仅仅是再类名作用域下额外增加的一些工具,方便使用。

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宗浩多捞

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值