跳至主要內容

特殊的成员函数

张威大约 4 分钟c/c++类和对象

特殊的成员函数

img
img

除了特殊的数据成员以外,C++类中还有两种特殊的成员函数:静态成员函数和 const 成员函数。我们 先来看看静态成员函数。

静态成员函数

成员函数也可以定义成静态的,静态成员函数的特点:

  1. 静态的成员函数的第一个参数位置没有this指针

  2. 静态的成员函数不能访问非静态的数据成员和非静态的成员函数

  3. 非静态的成员函数静态的数据成员和静态的成员函数

  4. 静态成员函数可以使用类名加作用符的形式进行调用(静态成员函数的特殊用法)

如下:

普通的成员方法特点:编译器会添加一个this形参变量

class Computer 
{
public:
    Computer(const char * brand, double price)
    : _brand(new char[strlen(brand) + 1]())
    , _price(price)
    {
        _totalPrice += _price;
    }
    
    //...
    static void printTotalPrice()
    {
        cout << "总价:" << _totalPrice << endl;
    }
    //...
    
private:
    char * _brand;
    double _price;
    static double _totalPrice;
};

对于静态成员函数,还可以直接通过类名进行调用,这也是的方式:

int main(void)
{
    Computer pc1("Huawei MateBook14", 5699);
    pc1.print();
    Computer::printTotalPrice();//通过类名直接调用
    return 0;
}

下面让我们再来看一个有意思的例子:

#ifndef __COMPUTER_H__
#define __COMPUTER_H__

class Computer
{
public:
    Computer(const char *brand, float price);
    Computer(const Computer &rhs);
    Computer &operator=(const Computer &rhs);
    void setBrand(const char *brand);
    void setPrice(float price);
    static void printTotalPrice();

    void print();
    ~Computer();

private:
    char *_brand;//8
    float _price;//4, 内存对齐
    static float _totalPrice;//4静态的数据成员不占类的大小,被类
                            //创建的所有对象所共享
};

#endif
void test4()
{
    cout << "sizeof(Computer) = " << sizeof(Computer) << endl;

    cout << "一台电脑都没有购买 : " << endl;
    Computer::printTotalPrice();

    cout << endl;
    Computer com1("huawei", 6000);
    cout << "com1 = ";
    com1.print();
    cout << "购买第一台电脑总价 : " << endl;
    com1.printTotalPrice();
    Computer::printTotalPrice();

    cout << endl;
    Computer com2("xiaomi", 8000);
    cout << "com2 = ";
    com2.print();
    cout << "购买第二台电脑总价 : " << endl;
    com2.printTotalPrice(); 
    com1.printTotalPrice(); 
    Computer::printTotalPrice();//可以使用类名加作用域限定符进行调用
    /* Computer::print();//error */
}

const成员函数

之前已经介绍了const在函数中的应用,实际上,const在类成员函数中还有种特殊的用法,把const关键 字放在函数的参数表和函数体之间(与之前介绍的const放在函数前修饰返回值不同),称为const成员 函数,其具有以下特点:

  1. 对于非const对象,既可以调用const版本的成员函数,可以调用非const版本的成员函数,情况下,调用非const版本的成员函数

  2. const对象调用const版本的成员函数,不能调用非const版本的函数

  3. const版本的成员函数与非const版本的成员函数可以重载,一般先写const版本的

  4. const版本的成员函数具有只读特性,不能进行写操作,所以对于不修改数据成员的情况,可以将成员函数用const修饰

其格式为:

类型 函数名(参数列表) const
{
    函数体
}

比如当给Computer类添加一个const的打印函数后,则其实现如下:

class Computer 
{
public:
    //...
    
     //const版本的成员函数可以与非const版本的成员函数进行重载(this指针是不一样)
    //一般建议先写出const版本的成员函数
    void Computer::print(/*  Computer * const this  */)
	{
    	/* this->_price = 10; */
    	/* printTotalPrice();//ok */
    	cout << "void print()" << endl;
        printf("brand : %p\n", _brand);
    	cout << "brand : " << _brand << endl
         	<< "price : " << this->_price << endl;
	}

	void Computer::print(/* const Computer * const this */) const
	{
    	/* this->_price = 10;//error */
    	cout << "void print() const " << endl;
    	printf("brand : %p\n", _brand);
    	cout << "brand : " << _brand << endl
         	<< "price : " << this->_price << endl;
	}
};
void test5()
{
    //非const对象既可以访问非const版本成员函数也可以访问
    //const版本的成员函数,但是默认情况下访问非const版本
    //的成员函数
    Computer com1("huawei", 6000);
    cout << "com1 = ";
    com1.print();

    cout << endl;
    //const int number = 10;
    //const对象只能访问const版本的成员函数,不能访问非const版本的成员函数
    const Computer com2("xiaomi", 8000);
    cout << "com2 = ";
    com2.print();

}

为什么const成员无法调用普通成员方法?

因为const成员的this指针类型为const T * const this,

普通成员方法要求传入的是T * const this,相当于试图T* <= const T*, 错误