[记录]常量指针参数的编译错误....

这里随手记录了一个关于常量指针参数的编译错误,

顺道引出指针常量和常量指针这个经常容易混淆的话题。

起因

 手动编译fear::vision模块的时候出现的编译错误

错误信息

VisionDefinition.cpp
error C2664: “fear::backend::iVision::NextEntity”: 不能将参数1 从“fear::Entity *”转换为 “const fear::Entity *&

        转换丢失限定符

错误类别

错误的类型转换

 

代码如下

//  获得视觉实体
void  VisionSymbolic::GetVisibleEntities(vector <  Entity *   >&  visible)
...
{

    Entity
* e = NULL;

    GetBackend().Reset();

    
while (GetBackend().NextEntity(e))

    ...
{

       visible.push_back(e);

    }


}
  //  GetVisibleEntities()

错误的原因:

const指针引用编译不能通过!

NextEntity的函数头如下:

bool  BackendVision::NextEntity( const  Entity *&  entity)

这是1个常量指针引用, 而不是指针常量引用

 

试验

首先使用VC8做了一下测试, 编译无法通过

1. 常量指针的引用,编译错误

void  testConstPtrRef(  const   int *&  intPtrRef)
{
    
return;
}


int  _tmain( int  argc, _TCHAR *  argv[])
{
    
int* testInt = 0;
    testConstPtrRef(testInt); 
// 错误!输入不是要求的常量指针引用 
    return 0;
}

在GCC下的同样也产生错误, 错误信息如下

main.cpp:15: error: invalid initialization of reference of type 'const int*&'
    from expression of type 'int*'
main.cpp:8: error: in passing argument 1 of `void testConstPtrRef(const int*&)
'

 

这种明显的错误在VC6和VC7是可以编译过的? 我没试过...谁试验下?

 

2. 使用了1个typdef, 被指定为指针IntPtr的常量引用,编译通过

typedef  int *  IntPtr;

void  testConstPtrRef(  const  IntPtr &  intPtrRef)
{
    
return;
}


int  _tmain( int  argc, _TCHAR *  argv[])
{
    IntPtr testInt 
= 0// Int* 在这里同样可以
    testConstPtrRef(testInt); // 通过!指针的常量引用
    return 0;
}


3. 把const 放在后面,指针类型的常量引用,编译通过

void  testConstPtrRef(  int *   const   & intPtrRef)

{

    
return;

}


int  _tmain( int  argc, _TCHAR *  argv[])

{

    
int* testInt = 0;

    testConstPtrRef(testInt);

    
return 0;

}

 

2和3在GCC下同样通过

修改GetVisibleEntities函数

下面还是回到编译问题上来, 一开始我直接定义vector< const Entity* > 返回。

typedef std::vector <   const  Entity *   >  EntityVec;  //  <- 这里用const

void  VisionSymbolic::GetVisibleEntities( EntityVec &  visible)

{

    
const Entity* e = NULL; <- 这里直接传const指针给NextEntity

    GetBackend().Reset();

    
while (GetBackend().NextEntity(e))

    
{

       visible.push_back(e);

    }
 

}
  //  GetVisibleEntities()

但是上面的方法在FEAR::VisionSymbolic里是无法这么写..

原因是

VisionSymbolic :  public  body::vision::iSymbolic

GetVisibleEntitiesiSymbolic接口的实现。所以我们还是只能在内部修改

但是我们又不能修改接口的实现为const Entity*那该怎么办呢

 

暂时只能用这种脑残做法了--------------使用const_cast

void  VisionSymbolic::GetVisibleEntities( std::vector < Entity *>&  visible)

{

    
const Entity* ce = NULL; //<- 此处依然是const, 为了获得实体

    GetBackend().Reset();

    
while (GetBackend().NextEntity(ce))

    
{

       visible.push_back( const_cast
<Entity*>(ce) ); // const_cast!

    }


}
  //  GetVisibleEntities()

 

结论

常量指针使用错误的可以使用如下方法解决:

1 把const写在参数类型后面

似乎boost和一些库里更倾向于把const放在后面, 大概就是为了避免出现上面的问题吧。

不过总觉得把const放后面感觉很奇怪, 大概是看前面看多了吧...

2 使用typedef声明别名

如上面typedef int*为IntPtr;

你可以使用类简单封装指针。

也可以使用一个这样的宏定义

#define  POINTER( Type )  /
typedef Type
*  CLASS##Ptr;

3 不改变函数体, 直接传常量指针参数

这个就是我上面用的方法。这样就不用修改内部实现。

4 使用const_cast

const_cast似乎一向都不受推荐使用来的?

以上....=  =||| 记录美....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值