假设我有一个源文件A.cpp:
#include<string>
struct A {
static const std::string a;
static const std::string b;
static const std::string c;
};
const std::string A::a{"1"};
const std::string A::b{"2"};
const std::string A::c{"3"};
并且要在另一个翻译单元中使用A::b
。通常的方法是将A.cpp
分为声明A.hpp
和定义,包括第一个。
#include<iostream>
#include<A.hpp>
int main(){
std::cout << A::b << "\n";
return 0;
}
那当然可以,但是我想避免包含类声明,因为在我的情况下,A
很大并且具有繁琐的依赖关系。
理想情况下,我想要类似
struct A;
external const std::string A::m;
但是会产生不完整的类型错误。
可以依靠通过其他非类全局变量进行链接。
const std::string A::b{"2"};
const std::string* bptr{&A::b};
并在另一个源文件中将其声明为
extern const std::string* bptr;
这是正确的方法,但对我来说却有点丑陋,因为需要引入多余的实体。
另一种对我有用的把戏。
struct A {
static const std::string b;
};
int main(){
std::cout << A::b << "\n";
return 0;
}
它看起来不错,但很笨拙,即使是私人会员也可以使用。合法吗就是说,有什么定义这种行为的东西吗?
答案 0 :(得分:1)
最后显示的技巧可能是最糟糕的黑客攻击,并且有一天会适得其反-因为它“掩盖”了另一个定义。这里没有“中间”(除了许多“ hacks”之外),要么使类定义完整显示,要么将字符串定义从类中移出。
它看起来不错,但很笨拙,即使是私人会员也可以使用。合法吗?
取决于上下文,如果第三个单元同时使用了这两个单元,您将回到原始问题上。它之所以私下工作是因为它是另一种定义,因此一开始就不是私下的。
答案 1 :(得分:0)
乍一看,最后一个变种在我看来是某种黑魔法。但是我认为它为什么起作用的越多,我认为它几乎是有效的。
一个定义规则。实际上有两个实体要看:一个字符串和一个类。
该字符串完全遵循一个定义规则。那让我感到困惑。它与在不同来源中声明相同的全局变量没有太大区别。如果存在相同定义的其他引用,则链接程序永远不会有任何问题。这种双重声明没有做任何特殊的事情,只是提供了两个引用相同的定义。而且,是的,链接器不在乎不同声明的不同访问修饰符。
该类违反了一个定义规则。在提供的示例中,差异不会破坏任何内容。但是,将非静态成员添加到定义之一,并尝试在具有不同类定义的翻译单元之间移动对象,这开始引起人们的注意。
从技术上讲,维持这两个定义并不难,但无论如何都要避免。
而且,也许我会坚持昆汀建议的通过附加功能提供访问权限的解决方案。
答案 2 :(得分:0)
如果json_normalize
中仅包含静态成员变量,则可以将A
从结构更改为名称空间(将A
更改为struct
,并摆脱掉所有变量名前面的namespace
)。然后,您可以将“ A.h”拆分为多个头文件,以便仅包含所需的部分。所有变量的定义可以在一个.CPP文件中,也可以在多个文件中分割。