C++之const在类用法小结

C++之const在类用法小结

const指针指向问题

例1:

int main()

{

const int a=10;

//int *p=&a;//因为a是个const常量,而指针p可以改变a的值,相互矛盾

const int *s=&a;

//int *const p1=&a;//error 原因同上

const int *const p2=&a;

 

int b=10,c=20;

int *p=&b;

int *q=p;

*q=100;//q改变的是b的值,

q=&c;//q的改变不会影响p

return 0;

}

例2:

void fun(int *s)

{

*s=100;

cout<<*s<<endl;//100

s=new int (200);//这里s重新指向了一个堆区,并不影响p

}

int main()

{

int a=10;

int *p=&a;

fun(p);

cout<<*p<<endl;//100

return 0;

}

例3:

 

 

    int a=10,b=20;

//const int *s=&a;  //p1,p3错误

int *const s=&a;//p1,p2,p3,p4都正确,因为他们的改变不会影响s

//const int *const s=&a; //p1,p3错误

int *p1=s;

const int *p2=s;

int *const p3=s;

const int *const p4=s;

例4:

指针引用

 

   int a=10,b=20;

int *s=&a;

int *&p=s;//s是指针的引用,所以s的改变会影响p

const int * &p1=s;//VC6.0上是对的,2012中是错的

int const * &p2=s;//VC6.0上是对的,2012中是错的

int * const &p3=s;//不允许通过改变p3的值去改变s

int * &const p4=s; //vc和2012都有警告

const int *const &p5=s;

const int *&const p6=s;//VC6.0上是对的,2012中是错的 //vc和2012都有警告

const int *const &const p7=s;//vc和2012都有警告

 

   int a=10,b=20;

int *const s=&a;

// int *&p=s;//error

// const int * &p1=s;//error

// int const * &p2=s;//error

int * const &p3=s;

// int * &const p4=s; //error

const int *const &p5=s;

// const int *&const p6=s;//error

 

const int *const &const p7=s;

类1

class Test

{

private:

int value;

public:

Test(int x=0):value(x) {}

Test(const Test &it):value(it.value) {}

Test & operator=(const Test &it) 

{

if(this != &it)

{

value = it.value;

}

return *this;

}

~Test() {}

public:

int GetValue() { return value;}//产生临时变量以寄存器返回,常性,不允许取地址

int GetValue() const { return value;}

 

int & GetRef() { return value;}//以引用返回,不产生临时变量

const int & GetRef() const { return value;}

   //Value为常性,但以引用返回时可能通过变量改变value的值,故此函数前应加const

 

int * GetPtr() { return &value;}//将临时指针变量放在寄存器中返回,具常性,即指向不改变,不允许取地址

const int * GetPtr() const  { return &value;}

};

 

实例1:

 void main()

{

Test t1(10);

const Test t2(20);

int a1   = t1.GetValue();//Y

//int &b1 = t1.GetValue();//N:int tmp = t1.GetValue();tmp为常性

const int &c1 = t1.GetValue();//Y

//int tmp = t1.GetValue();const int &c1 = tmp;

// int *p1= &t1.GetValue();//N 临时变量的值存在寄存器中,不允许取寄存器的地址

   int (Test:: *pfn)();

pfn = &Test::GetValue;

pfn = t1.GetValue;

 

int a2        = t2.GetValue();//Y

   //int &b2       = t2.GetValue();//N

const int &c2 = t2.GetValue();//Y

//int *p2       = &t2.GetValue();//N

}

实例2:

void main()

{

Test t1(10);

const Test t2(20);

int a1        = t1.GetRef();//Y

int &b1       = t1.GetRef();//Y

const int &c1 = t1.GetRef();//Y

int *p1       = &t1.GetRef();//Y

 

int a2        = t2.GetRef();//Y

//int &b2    = t2.GetRef();//N  value为const,引用需为const

const int &c2 = t2.GetRef();//Y

//const int *p2  = &t2.GetRef();//N

}

实例3

 

void main()

{

Test t1(10);

const Test t2(20);

int *a1        = t1.GetPtr();

//int *&b1       = t1.GetPtr();//返回值为常性

  int *const &c1 = t1.GetPtr();

//const int **p1       = &t1.GetPtr();//不能对寄存器取地址

 

//  int *a2        = t2.GetPtr();//可能通过改变地址改变value的值

const int *a2  = t2.GetPtr();

// int *&b2       = t2.GetPtr();

const int *const &c2 = t2.GetPtr();

//  const int **p2 = &t2.GetPtr();

}

实例4

void main()

{

int a=10,b=20;

const int *const s = &a;//s指向a的地址,不允许通过s改变a,也不允许s指向别人

// int *&p = s;//指针引用,可以通过p改变s的指向

 

//  const int *&p1 = s;

// int const *&p2 = s;

// int * const &p3 = s;

// int * & const p4 = s;

 

const int * const &p5 = s;

// const int * & const p6 = s;

}

 

实例5

class Test

{

int *ptr;

int ar[5];

public:

Test(int x=0):ptr(new int(x)) 

{

for(int i = 0;i<5;++i)

{

ar[i] = i;

}

}

~Test() { delete ptr;}

void fun1()

{

*ptr = 100;

delete ptr;//删除堆区的new区域,编译可通过

ptr = new int(200);

ar[2]=100;

}

void fun2() const

{

*ptr = 100;//ptr自身指向不变,指向空间的值改变,编译可通过

// delete ptr;

// ptr = new int(200);//ptr的指向改变,编译不能通过

//ar[2]=200;ar[2]自身改变了,编译不能通过

}

};

void main()

{

Test t1(10);

const Test t2(20);//指向不允许改变,指向地址的值可以改变

t1.fun1();

t1.fun2();

// t2.fun1();//常对象只能访问常方法

t2.fun2();

}

 

类2

class Test

{

private:

int *ptr;

public:

Test(int x=0):ptr(new int(x)) {}

~Test() { delete ptr;}

public:

int GetValue() { return *ptr;}//构建的临时对象在寄存器中,常性,不可取地址

int GetValue() const { return *ptr;}

 

int & GetRef() { return *ptr;}//通过引用返回ptr指向的值,不产生临时变量

int & GetRef() const { return *ptr;}

const int &GetRef2()const{return *ptr;}

 

int * GetPtr() { return ptr;}

int * GetPtr() const { return ptr;}

 

int *& GetRPtr() { return ptr;}//

int *const & GetRPtr() const { return ptr;}

 

int ** GetPPtr() { return &ptr;}

int *const * GetPPtr() const { return &ptr;}

};

 

若为const对象,则ptr指向不允许改变,指向地址的值可变

实例1

 

int GetValue() { return *ptr;}//返回ptr指向的值,构建的临时对象在寄存器中,常性,不可取地址

int GetValue() const { return *ptr;}

 

void main()

{

Test t1(10);

const Test t2(20);

int a1        = t1.GetValue();

//int &b1       = t1.GetValue();//临时变量为常性,不可通过引用改变它的值

const int &c1 = t1.GetValue();

//int *p1       = &t1.GetValue();//构建的临时对象在寄存器中,不可取地址

 

int a2        = t2.GetValue();

// int &b2       = t2.GetValue();

const int &c2 = t2.GetValue();

// int *p2       = &t2.GetValue();

}

实例2

int & GetRef() { return *ptr;}//通过引用返回ptr指向的值,不产生临时变量

int & GetRef() const { return *ptr;}//ptr指向不可变,指向的值可变

const int & GetRef1() const { return *ptr;}//ptr指向不可变,指向的值不可变

 

void main()

{

Test t1(10);

const Test t2(20);

int a1        = t1.GetRef();

int &b1       = t1.GetRef();

const int &c1 = t1.GetRef();

int *p1       = &t1.GetRef();

 

int a2        = t2.GetRef();

int &b2       = t2.GetRef();//允许通过改变引用来改变Ptr指向的值

const int &c2 = t2.GetRef();

int *p2       = &t2.GetRef();

 

int a3=t2.GetRef1();

// int &b3=t2.GetRef1();//

const int &c3=t2.GetRef1();

// int *p3=&t2.GetRef2();//

const int *p3=&t2.GetRef1();

}

 

实例3

 

int * GetPtr() { return ptr;}//以寄存器返回指向ptr指向的值的指针变量,常性,不可取地址

int * GetPtr() const { return ptr;}//ptr指向不可变,指向的值可变

const int *GetPtr1()const{return ptr;}//ptr指向不可变,指向的值不可变

 

 

void main()

{

Test t1(10);

const Test t2(20);

int *a1        = t1.GetPtr();

//int *&b1       = t1.GetPtr();//临时指针变量为常性

int *const &c1 = t1.GetPtr();

//int **p1       = &t1.GetPtr();//不可对寄存器取地址

 

    int *a2        = t2.GetPtr();

// int *&b2       = t2.GetPtr();

int *const &c2 = t2.GetPtr();

// int **p2       = &t2.GetPtr();

 

// int *a3       =t2.GetPtr1();

const int *a3=t2.GetPtr1();

// int *&b3      =t2.GetPtr1();

const int *const &b3=t2.GetPtr1();

// const int *&c3=t2.GetPtr1();

const int *const &c3=t2.GetPtr1();

}

 

实例4

 

int *& GetRPtr() { return ptr;}//返回ptr

int *const & GetRPtr() const { return ptr;}//ptr为常性,则不允许通过引用改变它值,即它的指向

const int *const&GetRPtr1()const{return ptr;}

 

Test t1(10);

const Test t2(20);

int *a1       =t1.GetRPtr();

int *&b1      =t1.GetRPtr();

const int *&c1=t1.GetRPtr();//

int **p1      =&t1.GetRPtr();

 

int *a2       =t2.GetRPtr();

// int *&b2      =t2.GetRPtr();//error

int *const &b2=t2.GetRPtr();

// const int *&c2=t2.GetRPtr();

    const int *const&c2=t2.GetRPtr();

//  int **p2      =&t2.GetRPtr();//error

int *const*p2 =&t2.GetRPtr();

 

// int *a3              =t2.GetRPtr1();//error

const int *a3        =t2.GetRPtr1();

// int *&b3             =t2.GetRPtr1();//error

const int *const &b3 =t2.GetRPtr();

// const int *&c3       =t2.GetRPtr1();//error

const int *const &c3 =t2.GetRPtr();

// int **p3             =&t2.GetRPtr1();//error

const int *const*p3  =&t2.GetRPtr();

实例5

int ** GetPPtr() { return &ptr;}//以寄存器中的临时地址变量返回

int *const * GetPPtr() const { return &ptr;}

const int *const * GetPPtr() const { return &ptr;}

 

 

Test t1(10);

const Test t2(20);

int **a1       =t1.GetPPtr();

// int **&b1=t1.GetPPtr();

    int **const&b1=t1.GetPPtr();

// const int **&c1=t1.GetPPtr();//error

int *const*const&c1=t1.GetPPtr();

// int ***p1      =&t1.GetPPtr();//无法对寄存器取地址

 

int *const*a2       =t2.GetPPtr();

int *const*const&b2 =t2.GetPPtr();//

int *const*const&c2=t2.GetPPtr();//

// int ***p2      =&t2.GetPPtr();//

 

const int *const *a3       =t2.GetPPtr1();//

const int *const *const &b3 =t2.GetPPtr1();//

const int *const* const&c3=t2.GetPPtr1();//

//int***p=&t2.GetPPtr1();//

类3

class Int

{

private:

int num;

public:

Int(int x = 0):num(x) { cout<<"Create Int: "<<this<<endl;}

Int(const Int &it):num(it.num) {cout<<"Copy Create Int: "<<this<<endl;}

Int & operator=(const Int &it)

{

if(this != &it)

{

num = it.num;

}

cout<<" = "<<endl;

return *this;

}

~Int() {cout<<"Destroy Int: "<<this<<endl;}

};

class Test

{

Int value;

public:

Test(const Int &x):value(x) {}

~Test() {}

public:

Int GetValue() { return value;}//返回构建于栈帧的临时对象,不具有常性,地址可取

Int GetValue() const { return value;}

 

Int & GetRef() { return value;}//返回构建于栈帧的value的引用

const Int & GetRef() const { return value;}

 

Int * GetPtr() { return &value;}//返回指向value的临时指针变量,自定义类型,不具常性

const Int * GetPtr() const { return &value;}

};

 

实例1

Int GetValue() { return value;}//返回构建于栈帧的临时对象,不具有常性,地址可取

Int GetValue() const { return value;}

 

Int a = 10,b=20;

Test t1(a);

const Test t2(b);

Int a1        = t1.GetValue();

Int &b1       = t1.GetValue();

const Int &c1 = t1.GetValue();

Int *p1 = &t1.GetValue();//指针为弱引用,函数结束后析构

   

 

Int a2        = t2.GetValue();

Int &b2       = t2.GetValue();//引用临时对象,即使改变临时对象的值也不会改变value的值

const Int &c2 = t2.GetValue();

Int *p2       = &t2.GetValue();//

实例2

Int & GetRef() { return value;}//返回构建于栈帧的value的引用

const Int & GetRef() const { return value;}

 

Int a = 10,b=20;

Test t1(a);

const Test t2(b);

Int a1        = t1.GetRef();

Int &b1       = t1.GetRef();

const Int &c1 = t1.GetRef();

Int *      p1 = &t1.GetRef();

 

Int a2        = t2.GetRef();

// Int &b2       = t2.GetRef();

const Int &c2 = t2.GetRef();

// Int *p2       = &t2.GetRef();

const Int *p2 = &t2.GetRef();

 

实例3

Int * GetPtr() { return &value;}//以寄存器返回指向value的临时指针变量,具有常性

const Int * GetPtr() const { return &value;}

 

Int a = 10,b=20;

Test t1(a);

const Test t2(b);

Int *a1        = t1.GetPtr();

// Int *&b1       = t1.GetPtr();

Int *const&c1 = t1.GetPtr();

// Int ** p1      = &t1.GetPtr();

 

// Int *a2        = t2.GetPtr();

    const Int *a2        = t2.GetPtr();

// Int *&b2       = t2.GetPtr();

// const Int *&c2 = t2.GetPtr();

const Int *const &c2 = t2.GetPtr();

// Int **p2       = &t2.GetPtr();

 

总结:

1、内置类型:

a.以值返回:返回构建于寄存器中,使用此值拷贝构造的临时变量,具有常性,不可对其进行取地址操作

b.以引用返回:不产生临时变量,可对其进行取地址操作

c.以指针返回:以寄存器返回临时指针变量,具有常性,不可对其进行取地址操作

2、自定义类型:

a.以值返回:返回构建在栈帧的临时对象,可取地址,不具有常性

b.以引用返回:不产生临时变量,可对其进行取地址操作

c.以指针返回:以寄存器返回临时指针变量,具有常性,不可对其进行取地址操作

3.指针引用:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值