C++中的常成员函数以及const用于函数重载

1.什么是常成员函数?

在类中可以含有普通成员函数和静态成员函数,而使用 const修饰的普通成员函数称为 常成员函数

const修饰的是普通成员函数中的this指针指向的内存空间

类的普通成员函数中都存在隐藏的 this指针,比如:

class Test
{
private:
    int a;
    int b;
public:
    Test(int a,int b)
    {
        this->a = a;
        this->b = b;
    }
    void printT()
	{
        cout << "a = " << this->a << ",b = " << this->b << endl;
    }

}


//在C++编译器底层,void printT()函数是这样实现的
void printT(Test *const this)  //是一个const型的指针,一旦实参传过来后,指针本身指向就不可以被修改
{
    cout << "a = " << this->a << ",b = " << this->b << endl;
    
  //类中的成员变量相当于结构体中的属性,用类定义对象T,相当于用
//结构体类型定义变量T, 然后对象T调用方法时 相当于结构体变量T调用方法,T此时是一个栈空间变量
//调用printT()函数方法时,T会将自己的变量内存空间首地址传给函数printT(),所以对象TT调用方法时相当于把自身的地址也传入了函数中作为一个参数,但C++编译器给我们隐藏了而已

}

这是C++底层绑定成员的方法,而常成员函数是指在此基础上再加一个 const 进行修饰,修饰 this指针指向的内存空间

void printT() const
{
    cout << "a = " << this->a << ",b = " << this->b << endl;
}

此时const修饰的是this指针所指向的内存空间,即指向的内存空间的量不可改变,映射到底层表现为

void printT(const Test *const this) 
{
    cout << "a = " << this->a << ",b = " << this->b << endl;
}

绿色const是普通成员函数和常成员函数均有的,表示的是 指针本身的指向一旦确定不可修改,即 指针常量

而红色const是在普通成员函数括号后面编程 自己添加的,表示的是 指针指向的内存空间的值不可被修改,是一个常量指针,从而this指针是一个指向常量的常量指针
此时该成员函数称为 常成员函数

2.常成员函数的特点:

由于常成员函数中 this指针指向常量,所以常成员函数不能够完成修改 类属性的值的操作,比如:

class Change:
{
private:
    int a;
public:
    void changeA(int A) // #1
    {
        this.a = A;
    }
    void changeA(int A) const // #2
    {
        this.a = A;
    }
}

在上方中,#2 的操作是错误的

同时还要注意:

3.

常成员函数 不能调用 普通成员函数(因为普通成员函数中可能出现更新成员属性值的操作),可以调用其他常成员函数

而普通成员函数是可以调用常成员函数的

4.const关键字来进行函数的重载,还是在上方change类中:

int getval(int val)
{
    return val+3;
}

int getval(int val) const
{
    return val - 3;
}

而两者互为重载

规则是 常对象(实例化时必须用const进行修饰)调用 常成员函数, 普通对象调用 普通成员函数

5.其他关于const位置的小结

还是对于函数,const来修饰函数的返回值

const来修饰函数的返回值时 分为 指针返回,值返回

5.1当函数是指针返回时,该返回值只能返回给 用 const修饰的同类型的指针

const int* getval()
{
    int* tmp = new int(10);
    return tmp;
}

由于函数返回指针所指向的值不能被修改,所以

int* a = getval();  //编译错误

const int* b = getval(); //正确

5.2当函数是值返回时,由于返回的值要赋值给另外一个内存空间,所以此时加不加const影响不大 

6.const 修饰成员变量

int const a;

const int a;

两者等价,定义常量a

const int* a;

int const* a;

两者等价,均为定义了 常量指针即指针指向的值不可改变

int * const a;

定义了一个 指针常量,即 指针的指向不可改变

7.const修饰函数参数

const修饰函数参数时,就带来了一个问题。是否可以 根据 函数参数中的 const来进行函数重载,答案是可以的

主要看的就是 函数中的 参数是否 等价于一样,如果等价于一样,则编译器提示错误,函数重定义

如果两者不等价,则根据参数类型发生函数重载

比如:

#include<iostream>  
using namespace std;  

void fun(const int i)  
{  
    cout << "fun(const int) called ";  
}  
void fun(int i)  
{  
    cout << "fun(int ) called " ;  
}  
int main()  
{  
    const int i = 10;  
    fun(i);  
    return 0;  
}

这样编译则会出错,提示重定义,而不是发生重载

原因在于 函数调用中存在实参和形参的结合,我们的实参  i=10; 不管有没有 const,都不会改变实参的值

再如:

#include<iostream>  
using namespace std;  
   
void fun(char *a)  
{  
  cout << "non-const fun() " << a;  
}  
   
void fun(const char *a)  
{  
  cout << "const fun() " << a;  
}  
   
int main()  
{  
  const char *ptr = "hello world";  
  fun(ptr);  
  return 0;  
}

其中, char* a 指向的是 字符串变量, const char * a指向的是 字符串常量,两者对于实参是不一样的,前者可以改变实参指向的值,而后者无法改变

但是对于下面的:

#include<iostream>  
using namespace std;  
   
void fun(char *a)  
{  
  cout << "non-const fun() " << a;  
}  
   
void fun(char * const a)  
{  
  cout << "const fun() " << a;  
}  
   
int main()  
{  
  char ptr[] = "hello world";  
  fun(ptr);  
  return 0;  
}

char* a 与 char* const a 前者是 指针变量,后者是指针常量, 但是由于 函数参数的 实参与形参结合, 两者对于实参来讲是一样的,并不会改变实参的值

所以,综上,函数参数中的 const是可以看做函数重载的标志,但是要视具体情况而言

此外,上面已经知道 带const的常成员函数和普通成员函数也是可以发生重载的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值