常见易错问题

类型转换

一、Const_cast

去除常量特性

 

二、Static_cast

普通类型转换和类继承的父指针到子类指针的转换(引用一样)

注意:不能用于对象本身,只转换不进行运行时类型检查

 

不能进行的转换:

1*p -- > int

2Aobj ---> Bobj

3Const --> non-const

总的来说,没有意义的转化,该转换都不能做到

 

三、Reinterpret_cast

转换类型:

1、无关的指针到指针(类型在继承层次中不相关也可以)

2、无关的引用到引用(类型无关)

例如:

class x{};

class y{};

 

x X;

y Y;

 

x* px;

y* py;

 

px = reinterpret_cast(py);

py = reinterpret_cast(px);

 

y& ry = Y;

x& rx = reinterpret_cast(ry);

 

3、指针到int

4Int到指针

5、函数指针

注意:此类型也不会进行类型检查

 

四、Dynamic_cast

继承层次的指针,引用进行转换。运行时进行底层对象类型检查。

注意:由于运行时类型信息存在对象的Vtable中,因此类中必须有一个虚函数。

 


 

引用

1、            必须在创建时初始化

2、            引用指向一个const值,就可以创建未命名值的引用,否则编译错误

例如:

const int& ref = 5; //正确

int& ref = 5; //错误

 

3、            引用的修改误区(引用指向不可更改)

引用一旦创建它的指向就不能在修改,可以改变它的值(即指向的变量的值)

例如:  int a = 10, b = 20;

Int & ra = a;

cout << ra << endl;

cout << a << endl;

 

ra = b; //改变只是ra的值也就是a的值,并不会改变指向

cout << ra << endl;

cout << a << endl;

 

当你写出如下代码来绕过这条限制时:

Ra = &b; //错误

//表达式的两侧的类型不匹配。右侧&b是一个指针,左侧是int变量的引用,而不是指针的引用。

 

当引用给引用又会如何:

Int &rb = b;

ra = rb; //依然是赋值操作,而不会改变ra指向。

 

4、            指针的引用,引用的指针,引用的引用:

指针的引用声明方式:类型+*+&+refname = pointName

例如:

int* pInt = &a;

int* &rPInt = pInt;

cout << *rPInt <

 

int& *pra = ra; //不能声明引用的指针

int& &rra = ra; //不能声明引用的引用

 

5、            取引用的地址和取引用所指变量的地址是一样的;

例如:

cout << &ra <  //0012FF7C

cout << &a < //0012FF7C


6、            引用数据成员

当数据成员是引用时必须依靠成员初始化列表完成,不能通过构造函数体中完成。这样的原因是:如果引用不指向其他变量就无法存在。

例如:

class x

{

public:

       x(const int& num_ = 10):num(num_)

       {     

              cout << "x's " << num << endl;

       }

private:

       const int #

};

 

7、            引用参数

当函数参数为引用参数时,对被调用函数的参数修改就会修改外部调用代码的实参。因为可以把这种现象看成是实参的别名,就像上述引用的讨论一样。引用参数提高了程序的效率,因为减少了拷贝构造的调用操作。

 

引用参数带来的好处:

1、            效率:当复制大对象时花费很长时间,传递对象或指针会节省时间。

2、            正确性:不是所有的对象都允许传值,即使传值,也不一定就能正确的完成深拷贝操作。支持此操作,动态分配的对象必须提供定制的拷贝构造。

运用时机:对于内置类型,不需要修改实参,就应使用传值方式。其他都可以使用引用。

 

8、            引用返回值

当返回值是引用时,引用所对应的变量即将销毁,它所指向的数据将会出现问题,因为变量的生命周期已经结束。

 

运用时机:

1、当返回值是引用时,一般是出于效率的考虑,这样可以避免不必要的复制操作,只有当前对象在函数结束后依然存在的情况下。

2、为了实现链式操作

 

9、            与指针的比较:

1、            使程序清晰明了

2、            代码安全(不存在无效的引用)

准则:除非动态分配或在其他改变或释放指针指向的值,否则都应使用引用而不是指针


Const 应用事项

const修饰变量(必须初始化)

1、定义常量

        例如:const int arraysize = 10;

2、指针常量,常量指针

const和类型同在*的左侧时:(常量指针)

如: Const + 类型 + * + point 类型 + const + * + point

指针指向可以改,指针指向的值是不能通过指针进行修改。

      

const 紧靠变量的左侧时:(指针常量)

指针指向不可改,指针指向的值是可以通过指针进行修改。

      

3const引用

Int a = 50;

Const int& ra = a; //const int& 等价 int const&

ra = 4; //不能通过引用修改a,可以直接修改a

a = 100;

cout << ra <

      

总结:修饰的目标在于 const * 的左边,还是右边。

左边修饰的是指针的内容,右边修饰的是指针的指向

 

const修饰函数

const对象只能调用const成员函数

const对象都两者都可调用

const成员函数只能调用const成员函数

 

const修饰参数

防止参数被修改(代表输入参数)

Const引用作参数,既提高效率,有防止修改实参

 

Const修饰返回值

 

  

 


Static使用

Static内部连接符(匿名命名空间也可达到此效果)     

只在声明它的当前编译单元可以使用

Consttypedef默认都是内部连接

 

Extern外部连接符

多个编译单元都可使用

Consttypedef默认都是内部连接,可以是extern指定外部连接。

把一个名字指定为外不连接时,编译器把它当作声明来对待。所以编译器不会分配空间,因此,必须提供另外的定义。

 

Static变量(记忆性变量)

函数中的static变量,只初始化一次,下次用上次的值。

 

类中的static变量(准侧:采用对象内维护变量的状态)

与类关联而不是与类对象关联,对象拥有的是副本

 

static初始化

mian前执行,默认初始化零值,类中的也是一样。

准侧:不同源文件中非局部变量初始化顺序不确定。

 

Static函数没有this指针只能访问静态成员

 

你可能感兴趣的:(c++历程,编译器,class,c)