你如何 "declare" 全局结构?
How do you "declare" a global struct?
我有一个 .h 文件声明 3 different/similar class:
#ifndef _ICUSTOMCONTROLS_
#define _ICUSTOMCONTROLS_
class ICustomKnob1 : public IKnobControl
{
private:
// ..
public:
// ..
};
class ICustomKnob2 : public IControl
{
private:
// ..
public:
// ..
};
class ICustomButton : public IButtonControl
{
private:
// ..
public:
// ..
};
#endif // !_ICUSTOMCONTROLS_
我有一个定义这些 class 的 cpp 文件。我将 .h 包含在 cpp 中,也包含在项目(这是一个 DLL)中的其他 .h/.cpp 文件中。
此时,在 CPP 中,我想对所有 3 个 classes 使用 common/global 结构 (IText
)。如果我在 .h 中添加声明:
IText gTextCustomControl;
事实上它 "define" 它,所以我在编译时收到 LNK1169 one or more multiply defined symbols found
错误消息(正如我所说,我多次添加这个 .h)。
我可以在 .cpp 文件中添加它(具有真实定义):
IText gTextCustomControl = IText(12, &COLOR_WHITE, "Arial", IText::kStyleBold, IText::kAlignCenter, 0, IText::kQualityDefault);
但我永远无法确定在 DLL 中什么时候这将是 "processed"(也许以后是 classes 的 CTOR?也许更多次,浪费资源?)。我认为这不是一个好方法。
我也可以在 .h 上添加 extern 并按上面的方式定义它,但出于安全原因更糟(有人可以从 "extern" 访问它)。
你会如何处理这种情况?或者它不可能跨对象共享一个公共结构?
如果您在 .cpp 中创建全局变量,则无法保证它会先于其他全局变量进行初始化(请参阅 §3.6.3/2 [basic.start.dynamic] ),特别是:
// dll.cpp
IText gTextCustomControl = ...;
ICustomKnob2::ICustomKnob2 () {
gTextCustomControl.doSomething();
}
// main.cpp
ICustomKnob2 knob2; // Oops! gTextCustomControl may be initialized after this.
如果你想确保 gTextCustomControl
在你需要的时候初始化,你可以把它的声明放在函数或某种单例中 class,例如:
IText& get_gTextCustomControl () {
static IText ins(12, &COLOR_WHITE, "Arial", IText::kStyleBold,
IText::kAlignCenter, 0, IText::kQualityDefault);
return ins;
}
然后使用它代替全局变量,这将确保在使用它之前构造实例。
ICustomKnob2::ICustomKnob2 () {
get_gTextCustomControl().doSomething();
}
显然,这会延迟 gTextCustomControl
的构造到首次使用,这可能不是您想要的。
"Bt I will never sure in the DLL when this will be "processed”(也许以后是类的CTOR?
这确实是正确的关注。 DLL 全局变量将从 DllMain
构建,并且 DllMain
受到 严重 的限制。您不能从那里加载其他 DLL(加载程序锁定),也不能执行任何会强制 Windows 加载其他 DLL 的操作。所以使用来自其他 DLL 的函数通常也被禁止(例外:如果你的 A.DLL 导致你的 B.DLL 被加载,那么 B.DLL 可能会调用来自 A.DLL 的函数。)。 =15=]
正确答案:
IText& getTextCustomControl();
...
IText& getTextCustomControl() {
static IText retval (12, &COLOR_WHITE, "Arial", IText::kStyleBold,
IText::kAlignCenter, 0, IText::kQualityDefault);
return retval;
}
这会在第一次调用 getTextCustomControl
时初始化对象,这通常会在所有 DllMain()
函数完成后发生。
我有一个 .h 文件声明 3 different/similar class:
#ifndef _ICUSTOMCONTROLS_
#define _ICUSTOMCONTROLS_
class ICustomKnob1 : public IKnobControl
{
private:
// ..
public:
// ..
};
class ICustomKnob2 : public IControl
{
private:
// ..
public:
// ..
};
class ICustomButton : public IButtonControl
{
private:
// ..
public:
// ..
};
#endif // !_ICUSTOMCONTROLS_
我有一个定义这些 class 的 cpp 文件。我将 .h 包含在 cpp 中,也包含在项目(这是一个 DLL)中的其他 .h/.cpp 文件中。
此时,在 CPP 中,我想对所有 3 个 classes 使用 common/global 结构 (IText
)。如果我在 .h 中添加声明:
IText gTextCustomControl;
事实上它 "define" 它,所以我在编译时收到 LNK1169 one or more multiply defined symbols found
错误消息(正如我所说,我多次添加这个 .h)。
我可以在 .cpp 文件中添加它(具有真实定义):
IText gTextCustomControl = IText(12, &COLOR_WHITE, "Arial", IText::kStyleBold, IText::kAlignCenter, 0, IText::kQualityDefault);
但我永远无法确定在 DLL 中什么时候这将是 "processed"(也许以后是 classes 的 CTOR?也许更多次,浪费资源?)。我认为这不是一个好方法。
我也可以在 .h 上添加 extern 并按上面的方式定义它,但出于安全原因更糟(有人可以从 "extern" 访问它)。
你会如何处理这种情况?或者它不可能跨对象共享一个公共结构?
如果您在 .cpp 中创建全局变量,则无法保证它会先于其他全局变量进行初始化(请参阅 §3.6.3/2 [basic.start.dynamic] ),特别是:
// dll.cpp
IText gTextCustomControl = ...;
ICustomKnob2::ICustomKnob2 () {
gTextCustomControl.doSomething();
}
// main.cpp
ICustomKnob2 knob2; // Oops! gTextCustomControl may be initialized after this.
如果你想确保 gTextCustomControl
在你需要的时候初始化,你可以把它的声明放在函数或某种单例中 class,例如:
IText& get_gTextCustomControl () {
static IText ins(12, &COLOR_WHITE, "Arial", IText::kStyleBold,
IText::kAlignCenter, 0, IText::kQualityDefault);
return ins;
}
然后使用它代替全局变量,这将确保在使用它之前构造实例。
ICustomKnob2::ICustomKnob2 () {
get_gTextCustomControl().doSomething();
}
显然,这会延迟 gTextCustomControl
的构造到首次使用,这可能不是您想要的。
"Bt I will never sure in the DLL when this will be "processed”(也许以后是类的CTOR?
这确实是正确的关注。 DLL 全局变量将从 DllMain
构建,并且 DllMain
受到 严重 的限制。您不能从那里加载其他 DLL(加载程序锁定),也不能执行任何会强制 Windows 加载其他 DLL 的操作。所以使用来自其他 DLL 的函数通常也被禁止(例外:如果你的 A.DLL 导致你的 B.DLL 被加载,那么 B.DLL 可能会调用来自 A.DLL 的函数。)。 =15=]
正确答案:
IText& getTextCustomControl();
...
IText& getTextCustomControl() {
static IText retval (12, &COLOR_WHITE, "Arial", IText::kStyleBold,
IText::kAlignCenter, 0, IText::kQualityDefault);
return retval;
}
这会在第一次调用 getTextCustomControl
时初始化对象,这通常会在所有 DllMain()
函数完成后发生。