多重定义,安全防护
multiple definition with safe guard
header.h
#ifndef HEADER_H_
#define HEADER_H_
#include "cstdint"
namespace Header {
namespace Header2 {
enum { s1, s2, s3 };
}
struct S {
uint32_t m_index;
S(uint32_t index) : m_index(index) {}
};
S s1(Header2::s1);
}
#endif
模板.h
#ifndef CLASS_H_
#define CLASS_H_
#include "header.h"
#include "iostream"
template <class T>
class Class {
public:
Class() {};
void doSomething();
};
template <class T>
void Class<T>::doSomething() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
#endif
模板.cpp
#include "template.h"
正文.cpp
#include <iostream>
#include "header.h"
#include "template.h"
class A {
};
int main() {
std::cout << Header::s1.m_index << std::endl;
Class<A> c;
c.doSomething();
return 0;
}
$ g++ -Wall body.cpp template.cpp -o body -O3 -std=c++0x
/tmp/ccUYtE0g.o:(.bss+0x0): multiple definition of `Header::s1'
/tmp/cca2YIRL.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
我认为安全防护#ifndef CLASS_H_
可以防止重复包含。但似乎不是。 可能我在那里错过了什么?
包含防护可防止由于标头两次包含在同一个源文件中而导致的编译器错误。它们不能防止由两个定义同一对象的源文件引起的链接器错误(通常通过包含包含所述定义的标头)。
为了避免后一种错误,请不要在头文件中定义对象。在标头中声明它,在一个源中定义它。喜欢这个:
// .h file
extern S s1;
// source file
Header::S Header::s1(Header::Header2::s1);
包含守卫仅阻止在同一翻译单元(相同的.cpp
文件)中包含两次相同的标头。当然,标头应该包含在多个文件中。有些内容可以在所有翻译单元中出现,也不能多次出现。其中之一是命名空间范围的变量定义。
要使s1
的定义仅是一个声明(可以出现在多个翻译单元中),您需要将其设为 extern:
extern S s1;
但是你需要在某处有一个定义,所以在单个.cpp
文件中,你需要有:
S s1(Header2::s1);
确保它们位于适当的命名空间中。
相关文章:
- 我可以对 std::array 使用自定义分配器来获取安全加密密钥吗?
- 假定 Windows 伪句柄的值是否安全/定义?
- 如何在没有动态内存分配(堆)的情况下为可变大小数组(矢量)定义安全容器或视图
- 实现没有不安全服务器凭据的自定义 AuthMetadataProcessor
- 黑匣子系统.自定义主机上的安全软件
- 编写安全包装类以管理用户定义对象的指针
- 使用 std::vector,为什么 &vec[0] 未定义的行为,而 vec.data() 是安全的?
- 定义,初始化全局const变量是安全的吗?
- std::regex对于用户定义的表达式安全吗?
- 当空变量没有定义时,按值传递它们是否安全
- 新的类型安全枚举是否定义为从 0 开始
- 这个无括号的C预处理器定义是否安全
- 在Bitfield定义中是安全的
- 为什么编译器在我定义_CRT_SECURE_NO_WARNINGS之后仍然警告我不安全的strtok
- 多重定义,安全防护
- 从c++中的派生类调用未在基类上定义的成员函数是否安全
- 如何以定义良好的线程安全方式将C++字符串传递给Java JNI
- C++:在自定义迭代器上删除后增量运算符是否安全
- 用用户定义的默认构造函数memset普通结构是否安全
- 将模板成员函数的专门化定义(带OUT默认体)放在源文件中是否安全