![](/img/trans.png)
[英]Why pointer to non-const member function can't point const member function and opposite?
[英]Why can't a pointer of a “struct with const member” type point to a “struct with non-const member”?
该代码无法编译:
struct s_t {
int a;
};
struct c_s_t {
const int a;
};
s_t s;
c_s_t *c_s = &s;
ibug@ubuntu:~ $ g++ -fsyntax-only t.cpp
t.cpp:10:15: error: cannot convert ‘s_t*’ to ‘c_s_t*’ in initialization
c_s_t *c_s = &s;
^
但是,此代码可以完美地编译:
int a, *pa = &a, **ppa = &pa, ***pppa = &ppa;
const int * const * const * const cpcpcpa = pppa;
我知道在任何级别上具有更高CV资格的指针都可以指向在任何级别上具有更低CV资格的对象,但是为什么结构不一样?
上面的问题陈述是一个更复杂问题的MCVE,其中我的朋友正在尝试在t_s_t<T>
和t_s_t<const T>
之间转换指针,其中t_s_t
是具有一个模板参数typename
的模板结构类型,而T
是一个任意类型。
原因是s_t
和c_s_t
是不同的类型。
即使将c_s_t
定义为:
struct c_s_t {
int a; // <-- non-const!
};
然后:
s_t s;
c_s_t *c_s = &s;
它仍然无法正常工作。
类型错误是您的问题,您只是在尝试分配错误的类型。
这将工作:
s_t s;
s_t *c_s = &s; //types are matching
这两个是不同的结构,它们是不可转换的。 它们具有相同的成员这一事实无关紧要,即使您从c_s_t
删除了const
,它也不会改变任何东西。
您的其他示例之所以有效,是因为您将修饰符应用于一种类型。 例如,这是完全合法的:
struct s_t {
int a;
};
s_t s;
const s_t const* cs = &s;
我了解在任何级别上具有更高CV资格的指针都可以指向在任何级别上具有较低CV资格的对象
这实际上是不对的,至少不是您所描述的那样。 只能任意添加最高的CV限定词(当然,指针本身也可以添加CV限定词!),在C和C ++中都是这种情况。
这是“任何级别”概念的反例,直接取自当前标准草案的[conv.qual/3]
:
[注意:如果程序可以将类型
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 }
—尾注]
无论如何,然后您会问:
但是为什么结构不一样呢?
当然,您可以将const T*
指向T
,但这不是您要做的。 此规则不适用于递归。 类可以容纳一个以上的成员,因此您的方法通常无法正常使用(单成员类不需要特殊的规则)。
在这种情况下,这两个类在布局上是兼容的,因此我希望reinterpret_cast
在大多数情况下都起作用:
struct s_t {
int a;
};
struct c_s_t {
const int a;
};
int main()
{
s_t s;
c_s_t *c_s = reinterpret_cast<c_s_t*>(&s);
}
但是,似乎在布局兼容性优点上的别名实际上定义不明确,因此最终最好还是重新考虑设计。
tl; dr:不同的类型是不同的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.