c++的this指针与常函数

this指针与常函数

成员函数是如何区别调用它的对象?
#include 
using namespace std;
​
class Test
{
    const int num;
public:
    Test(int num):num(num) {}
    void show(void)
    {
        cout << num << " " << &num << endl;
    }
};
​
int main(int argc,const char* argv[])
{
    Test t1(1234), t2(5678);
    t1.show();
    t2.show();
}
C语言中我们如何解决该问题:

由于C语言中的结构没有成员函数,只能定义普通函数,取函数名时,让它与结构有关联,然后在函数的第一个参数把结构变量的地址传递过来,从而区别每个调用它的结构变量。

在C++语言中该问题由编译器帮忙解决:

1、C++语言中的结构、联合、类可以定义成员函数,成员函数都会有一个隐藏的参数。

2、该参数就是个地址,也叫this指针,可以显式使用。

3、使用结构、联合、类对象可以直接调用成员函数时,编译器会自动计算对象的地址隐式的传递给成员函数。

4、所以在成员函数中可以区分是哪个对象调用了它,并且在成员函数内访问成员变量时,编译器帮我们隐式在每个成员变量前增加了this->,所以可以区别出每个对象的成员变量。

5、由于成员函数参数列表中都隐藏着this指针,所以普通的成员函数无法作为回调函数使用。

#include 
#include 
#include 
using namespace std;
​
class Test
{
    int num;
public:
    Test(int num):num(num){ }
​
    void* run(Test* this,void* arg)
    {   
​
    }   
    
    void sigint(int signum)
    {   
​
    }   
​
    void show(void)
    {   
        cout << num << " " << &num << endl;
    }   
};
​
int main(int argc,const char* argv[])
{
    signal(SIGINT,Test::sigint);
​
    pthread_t tid;
    pthread_create(&tid,NULL,Test::run,NULL);
​
    return 0;
}

6、显式使用this指针可以解决函数参数与成员变量同名的问题。

#include 
#include 
#include 
using namespace std;
​
class Test
{
    int num;
public:
    Test(int num):num(num){ }
    void setNum(int num)
    {
        this->num = num;
        cout << this->num << " - " << &this->num << endl;
    }
​
    void show(void)
    {
        cout << num << " " << &num << endl;
    }
};
​
int main(int argc,const char* argv[])
{
    Test t1(1234), t2(5678);
    t1.show();
    t2.show();
    t1.setNum(6666);
    t1.show();
}
常对象与常函数
什么是常函数

在成员函数的参数列表的末尾(小括号后面),用const修饰,这种成员就叫常函数。

class 类名
{
public:
    // 常函数
    返回值 函数名(参数列表) const
    {
        
    }
};
常函数的特点:

常函数隐藏的this指针具有cosnt属性。

什么是常对象

在定义结构、联合、类对象时,使用const修饰,这种对象就叫常对象。

const 类名 对象名;
const 类名* 指针变量 = new 类名;
常对象的特点:

使用常对象调用成员函数时,编译器计算出的对象地址(this)也具有const属性。

常对象有常函数的局限性:

1、常对象不能调用普通成员函数,只能调用常函数(构造函数和析构函数除外),但普通对象既可以普通成员函数,也可以调用常函数。

2、在常函数中不能显式修改成员变量,并且也不能调用普通的成员函数,只能调用常函数。

3、如果类的对象一定会被const修饰,那么它的成员函数都要定义为常函数。

4、如果类的对象可能被const修饰,也可能不修饰,那么它的成员函数要写两份,一份常函数,另一份普通成员函数。

mutable关键字的作用

如果常函数的const属性与函数的功能发生冲突,一定要修改成员变量,那么使用mutable关键字修饰一下需要在常函数中修改的成员变量。

#include 
#include 
#include 
using namespace std;
​
class Test
{
    mutable int num;
public:
    Test(int num):num(num){ }
​
    void setNum(int num) const
    {
        this->num = num;
        cout << this->num << " - " << &this->num << endl;
    }
​
    void show(void) const
    {
        cout << num << " " << &num << endl;
    }
};
​
int main(int argc,const char* argv[])
{
    const Test t(1234);
    t.show();
    t.setNum(23456);
    t.show();
​
    return 0;
}
空类的对象为什么占用1字节内存?

1、因为C++中的空的结构、联合、类里面有隐藏的成员函数。

2、成员函数的参数列表中有隐藏this指针,调用这些成员函数时就需要计算出对象的地址传递给成员函数。

3、空的类对象至少要在内存中占据一个字节,才可以计算出this指针,传递成员函数,完成函数调用。

你可能感兴趣的:(c++,开发语言)