我已经做了一些C ++已经有一段时间了,我有点生疏了。有人可以告诉我,如果这样的话可能会在向前声明一个类时声明一个类对象吗?
e.g。
/child::*[1]/child::*[1]
我特别要求,所以我可以像这样对象声明:
class MyClass MyObject;
/* ... */
class MyClass
{
public:
void MyVariable;
} MyObject;
与低iq方式相反,采取2行:
// Header.hpp
class MyClass extern MyObject;
// Source.cpp
class MyClass
{
public:
void MyVariable;
} MyObject;
答案 0 :(得分:0)
您可以将extern
放在类型前面(因为extern是一个存储类,而class MyClass
是类型):
extern class MyClass myObject;
以上直接回答了有关语法的原始问题。然而,由于显然有一些混乱,我认为值得花掉我的答案。
首先,标准(n3690)的相关摘录:
§3.1.2:
宣言是一个 定义 除非它声明一个函数而没有指定函数的主体(8.4),它 包含 EXTERN 说明符(7.1.1)或a 联动规范 25 (7.5)并且都不是 初始化 也不是 功能- 身体 ,它在类定义(9.2,9.4)中声明了一个静态数据成员,它是一个类名声明(9.1),它是 一个 不透明枚举声明 (7.2),它是一个 模板参数 (14.1),它是一个 参数声明 (8.3.5)a 函数声明器不是 声明符 一个 函数的定义 ,或者它是一个 的typedef 声明(7.1.3), 一个 别名声明 (7.1.3),a 使用声明 (7.3.3),a static_assert声明 (第7条),a 属性- 宣言 (第7条),a 空声明 (第7条),或a 使用指示符 (7.3.4)。
§3.2.5:
[注: 声明和表达式的规则描述了哪些上下文完成了类 类型是必需的。类类型 Ť 必须完整如果:
- 类型的对象 Ť 定义为(3.1),或
- 类型的非静态类数据成员 Ť 声明(9.2)或
- T. 用作a中的对象类型或数组元素类型 新的表达 (5.3.4),或
- 左值到左值的转换应用于引用类型对象的glvalue Ť (4.1),或
- 将表达式(隐式或显式)转换为类型 Ť (第4,5.2.3,5.2.7,5.2.9,5.4条), 或
- 一个不是空指针常量的表达式,其类型不是 简历 无效* ,转换为 类型指针 Ť 或参考 Ť 使用标准转换(第4条),a 的dynamic_cast (5.2.7) 或者a 的static_cast (5.2.9),或
- 类成员访问运算符应用于类型的表达式 Ť (5.2.5),或
- typeid的 运营商(5.2.8)或 的sizeof operator(5.3.3)应用于类型的操作数 Ť ,或
- 具有返回类型或参数类型类型的函数 Ť 定义为(3.1)或称为(5.2.2),或
- 具有类型基类的类 Ť 已定义(第10条)或
- 类型的左值 Ť 分配给(5.17)或
- 类型 Ť 是一个主题 alignof 表达式(5.3.6)或
- 一个 异常声明 有类型 Ť ,参考 Ť 或指向 Ť (15.3)。
- 结束说明]
现在,考虑问题中的第一个例子:
class MyClass MyObject;
/* ... */
class MyClass {} MyObject;
这是无效的,因为第一行是声明和定义,根据§3.1.2)。
第三个例子是有效的:
// Header.hpp
class MyClass;
extern MyClass MyObject;
// Source.cpp
class MyClass {} MyObject;
这是有效的,因为Header.hpp
中的第二行只是一个声明(第3.1.2节),此时MyClass
不一定是完整的类型(第一个要点)在第3.2.5节中。
答案中第二个例子的问题只是语法不正确。正如我上面所写,正确的方法是:
// Header.hpp
extern class MyClass myObject;
// Source.cpp
class MyClass {} myObject;
@Samer Tufail和@Frax建议这没用。也许它不是很有用,但我可以考虑以下用例:
转发声明类型以减少包含的标头数量。该类可以在另一个头中定义,仅当客户端代码需要访问全局对象的成员时才包含该类。
能够定义固定数量的全局对象,同时隐藏类定义(在源文件中)。可以使用自由函数来操纵这些对象。
在C API中包装全局对象(类类型):
3。的例子:
// header.hpp
struct MyClass
{
explicit MyClass(std::string s);
const char* getString() const { return m_str.c_str(); }
private:
std::string m_str;
};
extern "C"
{
MyClass myObject("some string");
const char* getString(const MyClass* obj) { return obj->getString(); }
}
// header.h (C API)
extern struct MyClass myObject;
const char* getString(const MyClass* obj);
还有其他方法可以做这些事情,但使用前向声明的类型是可能的。恕我直言@Cryptoman询问很少使用,但有趣的功能,并没有理由低估这个问题。
答案 1 :(得分:-1)
您只能拥有指向前向声明的类的指针或引用,否则它是不完整的类型。
class MyClass;
class MyOtherClass
{
public:
// MyClass* obj; pointer
// MyClass& obj - reference
};
为什么会如此?想象您现在MyClass obj
中有MyOtherClass
。当调用MyOtherClass
的ctor时,它必须构造MyClass
,这不可能发生,因为它没有实现和/或类型不完整。