如何在C++中启用从常量到常量的隐式类型转换
How to enable implicit type conversion from non-const to const in C++?
以下是代码的本质:
class DM
{
public:
int something;
DM() : something(0) { }
};
typedef DM * dm_t;
typedef dm_t & dm_ref_t;
typedef const DM * dm_const_t;
typedef dm_const_t & dm_cref_t;
int getSomething( dm_cref_t dm ) // CALLING getSomething DOES NOT COMPILE
{
return dm->something;
}
int getSomethingAgain( dm_const_t dm )
{
return dm->something;
}
int getSomethingOnceMore( dm_ref_t dm )
{
return dm->something;
}
int main()
{
dm_t dm = new DM;
getSomething( dm ); // COMPILER ERROR COMES FROM HERE
getSomethingAgain( dm );
getSomethingOnceMore( dm );
return 0;
}
这是编译器错误:
implicit_cast.cpp: In function ‘int main()’:
implicit_cast.cpp:31: error: invalid initialization of reference of type ‘const DM*&’ from expression of type ‘DM*’
implicit_cast.cpp:13: error: in passing argument 1 of ‘int getSomething(const DM*&)’
也就是说,我有一个非常量指针,我想把它传递给一个通过引用接受常量指针的函数。如果函数通过引用接受一个非常量指针或通过值接受一个常量指针,但通过引用的常量指针不接受非常量指针,那么一切都很好。
出于安全考虑,我希望函数采用常量指针;出于一些进一步发展的原因,我希望它能通过参考。自动从非常数转换为常量应该是完全安全的。为什么g++不表演演员阵容?
我想进一步讨论一个定义为getSomething的函数。如何在每次调用时不添加显式强制转换的情况下使这些调用合法化?
它没有这样做,因为在扩展typedefs之后,您有了
int getSomething( DM const* & dm )
{
return dm->something;
}
...
int main()
{
DM* dm = new DM;
getSomething( dm );
}
g++正确地不允许自动执行此操作,因为您要求对常量指针进行非常量左值引用。您当前有一个非常量指针。它不能创建临时值,因为临时值不能绑定到非常量左值引用。
现在,如果您通过常量引用获取指针,它会起作用,因为它可以绑定到临时指针。但是,我只是直接传递指针,因为通过常量引用传递指针没有任何值。
不允许这样做的原因是,如果允许的话,也会这样做(违背const
系统的目的)
const int i = 5;
void foo( const int* & p)
{
p = &i;
}
void bar()
{
int * p;
foo(p); // Normally not legal
*p = 6; // And this is why
}
话虽如此,每当我看到指针的引用时,我向开发人员提出的第一个问题就是他们为什么需要这样做。偶尔,这是因为您需要一个输出参数,但我不希望它被广泛使用。
查看C++11标准中的[conv.qual]
(4.4/4):
转换可以在第一个级别以外的级别添加cv限定符多级指针,受以下规则约束:。。。[注意:如果程序可以将T**类型的指针分配给const类型的指针T**(也就是说,如果允许下面的第1行),程序可以无意中修改了const对象(就像在第2行所做的那样)。
给出的例子是:
int main() {
const char c = ’c’;
char* pc;
const char** pcc = &pc; // #1: not allowed
*pcc = &c;
*pc = ’C’; // #2: modifies a const object
}
这是针对指向指针的指针进行解释的,但出于完全相同的原因,对指针的引用也是如此。
这更像C++名称"resolution"。在您的情况下,您有一个指向const DM
的指针,但您想要一个常量指针,因此必须使用typedef dm_const_t const & dm_cref_t
(对常量指针的常量引用)
提供更多细节:
当您声明const int * a
时,就是说a
是一个指向整数的常量指针。与int const * a
相同。
如果要引用类型,则声明int & b
,这意味着b
是对整数的引用。同理,const int & c
与int const & c
相同(const总是限定变量,而不是类型)。
因此,如果您想要对常量指针的常量引用,则使用第二种表示法更清晰(如果不使用typedef
s,也是唯一可能的表示法):int const * const & d
,这意味着d
是对整数常量指针的常数引用。使用typedefs:
typedef const int * int_cptr;
typedef const int_cptr & int_cptrcref;
证明:http://ideone.com/V48Kxe
您不能。
您传递的是指针,这可能意味着在函数执行后,可能会有两个对同一内存的不同引用,一个声明为常量,一个则声明为非常量。
如果使用非常量引用来更改内存,那么常量引用的底层内存会突然发生更改,这将是不正确的行为。
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 字符类型转换不兼容
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- 错误:请求从"常量字符 [5]"转换为非标量类型"字符串"
- 如何为具有常量类型的函数正确转换来自 DLsym 的返回值?
- 另一个:从"常量类型*"到"类型*"的转换无效
- 字符串常量之前的预期构造函数、析构函数或类型转换
- C++大小写中的类型转换常量字符串
- 具有常量/非常量指针类型的模板的自动类型转换
- C++中的部分常量类型转换
- 将常量字符* 类型转换为 int 数组
- 为什么将整数文本类型转换为指针值会导致非常量表达式
- 转换为常量类型,初始化数组
- 算术中的c++常量类型转换
- 如何在C++中启用从常量到常量的隐式类型转换