我在一个封闭类中有两个内部结构,在其中一个结构中,我有一个指向另一个结构类型的对象的指针成员。为了提高可读性并明确指出前向声明适用于需要它的结构,我将前向声明放在内部结构本身中。像这样
class Enclosing{
public:
struct InnerA{
struct InnerB; // forward declaration inside InnerA to improve readability
InnerB* b;
// other members
};
struct InnerB{
// lots of member variables
};
};
然后我在外面的某个地方有一个函数
void DoSomething(){
Enclosing::InnerA a;
// error incompatible types Enclosing::InnerB* and Enclosing::InnerA::InnerB*
Enclosing::InnerB* ptr = a.b;
}
据我了解,前向声明仅是一种告诉编译器类的方法,而不是定义完全不同的新类型。这是标准吗?如果是这样,是否有一种方法可以在结构内部包含前向声明而不会被视为其他类型?
答案 0 :(得分:7)
是的,它被认为是另一种类型。
声明将名称放入声明出现的范围。每个类都介绍自己的范围。因此,在您的情况下,您拥有Enclosing::InnerA::InnerB
,与Enclosing::InnerB
显然不同。
恐怕没有办法在当前范围之外的其他范围内声明名称。您只需在使用InnerB
的定义之前直接在Enclosing
内部声明InnerA
。
答案 1 :(得分:4)
您的前向声明嵌套了两次,您正在前向声明SELECT cd.id, cd.customer_id, cd.customer_name, cp.phone_number, cp.updated
FROM customer_data cd
LEFT JOIN customer_phones cp
ON cp.user_id=cd.customer_id AND cp.is_default_phone='1' AND cp.deleted IS NULL AND
cp.updated = (
select max(updated) from customer_phones
where user_id=cd.customer_id AND is_default_phone='1' AND deleted IS NULL
)
ORDER BY cd.id
,但是您的定义是针对Enclosing::InnerA::InnerB
的,因此您实际上正在前向声明其他类型。
您应该保持在同一级别:
Enclosing::InnerB
问题不是本质上的前向声明,就像您正在做的事情一样:
class Enclosing {
struct InnerB;
struct InnerA {
InnerB* ptr;
};
};
您会看到class Enclosing {
struct InnerA {
struct InnerB {
int data;
};
InnerB* ptr;
};
struct InnerB {
float data;
};
};
和Enclosing::InnerA::InnerB
确实是不同的类型,这是因为声明像普通声明一样保留了其局部性。