据我所知,指向int A::* p
之类的数据成员的指针并不保留该成员的实际地址,而是保留偏移量。
但是,我遇到了如下奇怪的情况:
class TEST
{
int k;
};
int main()
{
double TEST::* p;//why?
}
如何编译上面的代码段没有错误,因为 TEST 类实际上没有 double 类型的成员?(不需要诊断) ?)
更重要的是,cout<<p;
也可以无误地运行,尽管它可能是未定义的行为。
答案 0 :(得分:3)
您的示例代码:
double TEST::* p;
尽管TEST
没有任何double
成员,因此宣布指向双重成员的指针是合法的,因为将其设为非法是没有好处的。它会为标准添加一大块标准,没有任何好处 - 如果您尝试将此设置为空指针常量以外的其他任何内容,则会出现编译器错误。
代码段:
double TEST:* p;
std::cout << p << std::endl;
是未定义的行为(好的编译器会发出警告),原因与:
相同int i;
std::cout << i << std::endl
未定义。在这两种情况下,变量都没有值。
答案 1 :(得分:2)
在C ++中,允许类型为T C::*
的对象指向实际存在于C
的基类或派生类中的成员。换句话说,支持这样的代码:
using BD = double Base::*;
struct Base {
virtual ~Base() = default;
int k;
virtual BD getMember() const = 0;
};
这里,Base
没有double
类型的任何成员,但它需要具体的派生类来实现getMember
函数,该函数可能会返回一个指针其拥有 double
成员。稍后可以使用这样的指针通过基类访问该成员:
double getValue(const Base& b, BD p) {
return b.*p;
}
这里,参数b
实际上可以引用派生类类型的对象,而p
可以指向该派生类的适当double
成员。如果是这样,这段代码完全有效且定义明确。
如果您希望编译器警告未使用的代码或未初始化的变量,那么应该有命令行选项。
答案 2 :(得分:0)
您可能没有该类的定义:
class Test;
double TEST::* p;