为什么这个片段可以编译而没有错误?

时间:2018-02-19 08:54:44

标签: c++

以下是关于pointer to data member

用法的讨论

据我所知,指向int A::* p之类的数据成员的指针并不保留该成员的实际地址,而是保留偏移量。 但是,我遇到了如下奇怪的情况:

class TEST
{
 int k;
};
int main()
{
 double TEST::* p;//why?
}

如何编译上面的代码段没有错误,因为 TEST 类实际上没有 double 类型的成员?(不需要诊断) ?) 更重要的是,cout<<p;也可以无误地运行,尽管它可能是未定义的行为。

3 个答案:

答案 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;