const在函数中也有很大的作用。 4.const修饰传入参数。 函数传入参数声明为const,以指明使用这种参数仅仅是为了效率的原因,而不是想让调用函数能够修改该传入参数的值。同理,将对象指针参数或引用参数声明为const,函数将不修改由这个参数所指的对象。 例如:
#include
using namespace std;
//void change(const ing &a)也是一样的
void change(const int *a)//修饰传入的指针类型参数或者是引用型参数
{//该函数体内不能修改*a的值
cout<<”in change() a=”<<*a<<endl;
*a=*a+10;//invalid
}
int main()
{
int i=10;
int *p=&i;
change(p);
cout<<”in main() p=”<<*p<<endl;
}
编译结果:
5.修饰返回值的引用或者是修饰返回值为指针类型的指针
#include
using namespace std;
const int& Max(const int &a,const int &b)
{
//return a+5;//invalid
if(a>b)
return a;
else
return b;
}
int main()
{
int a=2;
int b=5;
int c;
c=Max(a,b);
cout<<c<<endl;
}
//return a+5;//是不可行的,因为a+5实际上是一个临时的int变量。
6.类的成员函数中const的使用 1):作为修饰的传入参数效果和上面4是一样的。 2):修饰返回对象的引用与5原理也是一样的,而且更为重要。 3):在成员函数的最后加上const修饰代表该函数不修改任何该对象的成语属性。 例如:
#include
using namespace std;
class A
{
private:
int num;
public:
A(int i):num(i){
}
void setNum(int i)
{
num=i;
}
int Max(const A &b)const //const代表该函数不改变该调用对象的任何成员函数
{
//this->num+=10;
//setNum(100); 也是不允许的,因为setNum()修改了该调用对象的num属性
if(this->num>b.num)
return this->num;
else
return b.num;
}
};
int main()
{
A a(10);
A b(5);
int max=a.Max(b);
cout<<max<<endl;
}
需要注意的是,在用const修饰类的成员属性的时候,const只是代表了只读属性,而不是一个常量。
#include
using namespace std;
class A
{
private:
const int SIZE=5;
int arr[SIZE];//这里会编译错误
};
还有一点就是,如果成员属性被const修饰,只能在声明的通过就进行初始化,或者是利用初始化器的方式初始化,而不能在构造函数体内初始化,这一点我会在以后的构造函数初始化内容里面说明。
—————————————————————————————————————————————————— //写的错误或者不好的地方请多多指导,可以在下面留言或者给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。 转载请注明出处:https://www.royalchen.com/ author:royalchen Email:royalchen@royalchen.com ———————————————————————————————————————————————————

为什么会这样呢? 请先看后面关于结构说明内容后再看这里的内容:
显而易见,普通的多重基层依次调用上一层父类的构造函数。这就说明了MI有时候不太好的情况了,那就是如果你不小心的话,就会从上一层继承关系中意外创建多个基类的对象,例如如果base里面有一个string name属性,那么D创建的时候就会创建两个string name的对象,而这个,不一定是你想要的结果。 现在,来测试一下父类中存在虚继承的情况。 测试代码:
可以看到,如果上一层继承中都是虚继承,那么,只会在最开始一次调用base基类构造函数。 那么,如果A不是虚继承呢?
看到虚继承的B,C依旧只是在最开始使调用了一次base,但是A类不再是虚继承,因此A类的构造函数也调用来一次base的构造函数. [admin@localhost csuper]$ ./c base created! //这是BC共同调用的base构造函数 base created! //这是调用A类的构造函数时,A类构造函数又调用了一次base的构造函数。 A created! 为了测试这一想法是否真是如此,这里我们利用控制变量法,仅使B类不是虚继承。
可以看出,结果正是如此。 同时发现了一个有趣的情况。当A,B,C都是虚继承base的时候,D虚继承C,看看结果又会如何?
可以看到,构造D的对象时,先调用了base,然后就到了调用C的构造函数了,说明编译器在构造的时候,是优先构造虚继承的对象的,这样就保证了构造A,B对象的时候,如果AB是虚继承于base,就不会创建多个从base定义的成员属性了。 但是如果C不是虚继承base,但D又是虚继承C的时候又会如何呢?
可以看出,第一个调用的base应该是属于A,B调用的,因此,其实上面的说法是不对的,因为如果是优先调用C的构造函数,输出应该是 base created! //如果是优先调用C C created! base created! //A,B调用的base应该在这里出现,但事实上却不是。 A created! B created! D created! ……….. 再看看下面的测试:
说实在的,输出是这样我是没有想到的。 base created! //这个base是哪一个调用的呢? base created! B created! base created! C created! 后来我再这样测试一下我就知道是为什么了。 令A,B,C均不虚继承与base,但是D继承与A,并且虚继承B,C,看结果
因此可以看出,上一次的第一个base是因为A而调用的base,也就是说,编译器是先检测上一层继承关系(A,B,C)中,哪一个是虚继承于再上一层的类(base),如果有,则优先调用该虚继承与base的类(也就是A)的基类的(也就是base)构造函数,然后再调用D中虚继承的类的构造函数(B,C),最后才调用A自己的构造函数,这里有点复杂,还是上一次测试的例子: base created! //这个base是因为A是虚继承与base时调用的,但是调用完之后并不直接调用A (A created!)