Tag: c ++-faq

什么是未定义的引用/未解析的外部符号错误,我该如何解决?

什么是未定义的参考/未解决的外部符号错误?什么是常见原因以及如何修复/预防它们? 编译C ++程序分为几个步骤,由2.2 指定(Keith Thompson的信用作为参考): 翻译语法规则的优先级由以下阶段指定[见脚注]。 如果需要,物理源文件字符以实现定义的方式映射到基本源字符集(引入行尾指示符的换行符)。[SNIP] 删除反斜杠字符(\)后面紧跟一个新行字符的每个实例,拼接物理源代码行以形成逻辑源代码行。[SNIP] 源文件被分解为预处理标记(2.5)和空白字符序列(包括注释)。[SNIP] 执行预处理指令,扩展宏调用,并执行_Pragma一元运算符表达式。[SNIP] 字符文字或字符串文字中的每个源字符集成员,以及字符文字或非原始字符串文字中的每个转义序列和通用字符名称,都将转换为执行字符集的相应成员; [SNIP] 相邻的字符串文字标记是连接的。 分隔标记的空白字符不再重要。每个预处理令牌都转换为令牌。(2.7)。由此产生的标记在语法和语义上进行分析并翻译为翻译单元。[SNIP] 翻译的翻译单元和实例化单元组合如下:[SNIP] 解析所有外部实体引用。链接库组件以满足对当前转换中未定义的实体的外部引用。所有这样的翻译器输出被收集到程序映像中,该程序映像包含在其执行环境中执行所需的信息。(强调我的) [脚注]实现必须表现得好像发生了这些不同的阶段,尽管实际上不同的阶段可能会折叠在一起。 在编译的最后阶段发生指定的错误,通常称为链接。它基本上意味着你将一堆实现文件编译成目标文件或库,现在你想让它们一起工作。 假设你定义的符号a在a.cpp。现在,b.cpp 宣布该符号并使用它。在链接之前,它只是假设该符号已在某处定义,但它还不关心在哪里。链接阶段负责查找符号并将其正确链接到b.cpp(实际上是与使用它的对象或库)。 如果您使用的是Microsoft Visual Studio,您将看到项目生成.lib文件。它们包含导出符号表和导入符号表。导入的符号将根据您链接的库进行解析,并为使用该符号的库.lib(如果有)提供导出的符号。 其他编译器/平台也存在类似的机制。 常见的错误信息error LNK2001,error LNK1120,error LNK2019对于微软的Visual Studio和undefined reference to 符号名称为GCC。 代码: struct X { virtual void foo(); }; struct Y : X { void foo() {} }; struct A { virtual ~A() = 0; }; struct B:

c++ – 什么是三法则?

什么是抄袭的对象是什么意思? 什么是复制构造函数和复制赋值运算符? 我什么时候需要自己申报? 如何防止复制对象? 介绍 C ++使用值语义处理用户定义类型的变量。这意味着对象被隐式复制到各种上下文中,我们应该理解“复制对象”实际意味着什么。 让我们考虑一个简单的例子: class person { std::string name; int age; public: person(const std::string& name, int age) : name(name), age(age) { } }; int main() { person a("Bjarne Stroustrup", 60); person b(a); // What happens here? b = a; // And here? } (如果您对该name(name), age(age)部分感到困惑,则将其称为成员初始化列表。) 特别会员功能 复制person对象意味着什么?该main功能显示两种不同的复制方案。初始化person b(a);由复制构造函数执行。它的工作是根据现有对象的状态构造一个新对象。赋值b = a由复制赋值运算符执行。它的工作通常稍微复杂一些,因为目标对象已经处于某种需要处理的有效状态。 由于我们自己既没有声明复制构造函数也没有声明赋值运算符(也没有声明析构函数),因此这些都是为我们隐式定义的。从标准引用:

C++ – 为什么在宏中使用明显无意义的do-while和if-else语句?

在许多C / C ++宏中,我看到宏的代码包含在看似无意义的do while循环中。这是一些例子。 #define FOO(X) do { f(X); g(X); } while (0) #define FOO(X) if (1) { f(X); g(X); } else 我看不出它do while在做什么。为什么不在没有它的情况下写这个? #define FOO(X) f(X); g(X) 该do ... while和if ... else在那里让这个后您的宏分号总是意味着同样的事情。假设你有类似你的第二个宏。 #define BAR(X) f(x); g(x) 现在,如果你要BAR(X);在一个if ... else语句中使用if语句的主体没有用大括号括起来,你会得到一个不好的惊喜。 if (corge) BAR(corge); else gralt(); 上面的代码将扩展为 if (corge) f(corge); g(corge); else gralt(); 这在语法上是不正确的,因为else不再与if相关联。在宏中用大括号包装东西没有帮助,因为大括号后面的分号在语法上是不正确的。 if