现在的位置: 首页 > 综合 > 正文

C++与C#对比学习:让对象变得像常量

2013年09月18日 ⁄ 综合 ⁄ 共 1784字 ⁄ 字号 评论关闭

我们知道如果不希望改变某个变量的值就用const修饰它,让它变为常量.基本类型和指针类型都能用const来修饰.数组也可以用const来修饰.

那你自然要问我们把class实例化成一个对象后,如果不希望修改对象中的成员变量,让对象变得像个常量一样该咋整呢?

你首先自然会想到把类中所有的成员变量都用const修饰不就得了.其实这确实是个办法拉,但是如果我们只是想某个类的一个实例对象弄得像常量啊.你这样用const整就真成了常量了,所有类的实例都只能当常量来处理了.这显然不行拉.

其实很简单,我们只要实例化类时加个const修饰下就OK,但是由于类不是个简单的类型.所以还涉及到一些特殊的操作.还是举个简单的例子看下.

class MyClass

{

public:

int age;

string name;

MyClass(int num,string str)

{

age = num;

name = str;

}

void Test() { Print();  }

void Print() const

{

std::cout<<name<<endl;

}

~MyClass(void);

};

const MyClass my(110,"arwen");        //实例化类时用const修饰.

my.age = 911;     //这样会出错,既然用const修饰了肯定就变得像常量一样,不能改变成员变量的值了.

my.Print();          //正确执行

my.Test();          //出错了

为啥调用my.Test()时会出错呢? 这就是特殊的地方了.当用const修饰一个对象后,此对象就只能调用const修饰的函数了(const必须放到函数变后面).而一般的函数是不能被调用了.

为啥这样其实很简单,出于一致性考虑.既然不让直接修改成员变量了.那任何潜在的有可能修改成员变量的操作都就禁止.因为一般函数中有可能会修改了成员变量值.所以干脆禁止调用.

函数后面加个const是代表啥意思呢.它是代表在此函数中不能修改成员变量的值.例如

void Print() const  { age = 456;}     //这样会出错.当然你如果在函数中修改其他不是成员变量的值就没问题.

const修饰的函数中如果有调用到其他函数,那被调用的函数也只能是后面被const修饰的.当然一般函数调用const修饰的函数是没啥限制的.

所以通过当用const修饰对象后

1.不能像my.age = 911这样直修改成员变量

2.对象只能调用被const修饰的函数 

3.被const修饰的函数中不能修改成员变量,且它也只能调用其他也被const修饰的函数.

通过这三点确保了成员函数在任何情况下都不会被修改.用构造函数赋值后就一直不变.

 

上面说到的用const修饰函数也可以单独用,不一定和const修饰对象配合用.单独用的话约定也是一样,函数中不能修改成员变量

 

上面说的是在C++中,那在C#中呢?

首先C#中一般把成员变量叫作字段.跟C++不同,C#中可以直接给字段赋值的.所以用const修饰类中的字段,然后赋值是没问题的.但显然我们很多时候是希望用构造函数来赋值的.那咋整呢?也像C++一样用个const修饰下就OK了吗.那不行.因为用const修饰引用类型时只能给赋值为null,那等于说那对象没任何用处了.当然C#自然有其他操作可以达到类似的效果.那就是通过属性加权限修饰符.

class MyClass

{

private int age;

private string name;

public int Age {

get{return age;}

}

public int Name {

get{return name;}

}

MyClass(int num,string str)

{

age = num;

name = str;

}

}

如果不希望用户修改字段.就把字段全部设为private的.然后用属性提供个接口.只有读的权限,不能修改.只有构造函数能赋值一次.那你可能会问其他成员函数会修改啊?

这就需要遵守一个约定了,就是类中其他函数别直接去用字段,也只是去用属性Age,Name.当然这只是推荐的作法,如果你实在想去直接用字段,去修改了.那就没办法了啊.

反正C#中使用了属性,推荐的作法就是在成员函数中直接用属性,别直接用字段了.

另外还有个办法就是用readonly修饰字段,这样就只能读不能修改了.

 

抱歉!评论已关闭.