如何在C ++中启用从非const到const的隐式类型转换?

时间:2014-04-29 17:40:23

标签: c++ casting

这是代码的本质:

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*&)’

也就是说,我有一个非常量指针,我希望将其传递给一个通过引用接受const指针的函数。如果函数通过引用接受非常量指针或按值接受const指针,则一切都很好,但是const引用指针不接受非常量指针。

出于安全考虑,我喜欢使用const指针的功能;出于一些进一步的发展原因,我希望通过引用传递它。从非const到const自动转换应该是完全安全的。为什么没有g ++执行演员表?

我想进一步使用像getSomething这样定义的函数。如果我每次调用它而不添加显式强制转换,我如何合法化这些调用?

4 个答案:

答案 0 :(得分:4)

它没有这样做,因为在扩展typedef后,你有

int getSomething( DM const* & dm )
{
  return dm->something;
}
...
int main()
{
  DM* dm = new DM;
  getSomething( dm );
}

g ++正确地不允许这样做,因为你要求对常量指针进行非常量左值引用。您目前有一个非常量指针。它不能创建临时的,因为临时不能绑定到非const左值引用。

现在,如果您通过常量引用获取指针,它将起作用,因为它将被允许绑定到临时。但是,我只是直接传递指针,因为通过常量引用传递指针没有值。

这是不允许的原因是因为如果是这样的话,那么(违背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
}

现在,所有这一切,只要我看到对指针的引用,我向开发人员提出的第一个问题就是为什么他们需要这样做。有时,它是因为你需要一个输出参数,但它不是我希望普及的东西。

答案 1 :(得分:2)

在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
}

这是针对指针的指针解释的,但出于完全相同的原因,同样适用于对指针的引用。

答案 2 :(得分:1)

这更像是C ++名称“resolution”。在你的情况下,你有一个指向const DM的指针,但你想要一个const指针,所以你必须使用typedef dm_const_t const & dm_cref_t(对const指针的const引用)

提供更多详情:

当您声明const int * a时,您说a是一个指向整数的常量指针。它与int const * a相同。

如果要引用类型,则声明int & b,这意味着b是对整数的引用。以同样的方式思考,const int & cint const & c相同(const总是限定变量,而不是类型)。

所以,如果你想要一个对const指针的const引用,那么使用第二种表示法会更清楚(如果不使用typedef s则唯一可能的那样):int const * const & d,意思是{{1} }是对整数的常量指针的常量引用。使用typedef:

d

证明:http://ideone.com/V48Kxe

答案 3 :(得分:0)

你不能。

你正在通过指针传递,这意味着在执行函数之后,可能存在对同一内存的两个不同引用,一个声明为const,一个声明为非const。

如果非const引用用于更改内存,那么const引用突然会使其底层内存突然改变,这将是不正确的行为。