是否允许类在程序中的不同翻译单元之间具有不同的定义?
Are classes allowed to have different definitions across different translation units in a program?
假设每个翻译单元中最多定义一次类,在不同的翻译单元中以不同的方式定义类是否格式良好?
用例是在没有动态分配的情况下访问实现详细信息。C++代码将对 C 库已分配的指针进行操作。
例如,请忽略内存泄漏。
普通.hpp
#pragma once
namespace Test {
class Impl;
class A {
void *ptr;
A(void *ptr) : ptr(ptr) {}
friend class Impl;
public:
int plus_one();
};
class B {
void *ptr;
B(void *ptr) : ptr(ptr) {}
friend class Impl;
public:
int plus_two();
};
class Factory {
public:
A getA(int val);
B getB(int val);
};
} // namespace Test
答.cpp
#include "common.hpp"
namespace Test {
class Impl {
public:
static int as_int(A *a) { return *static_cast<int *>(a->ptr) + 1; }
};
int A::plus_one() { return Impl{}.as_int(this); }
} // namespace Test
B.cpp
#include "common.hpp"
namespace Test {
class Impl {
public:
static int as_int(B *b) { return *static_cast<int *>(b->ptr) + 2; }
};
int B::plus_two() { return Impl{}.as_int(this); }
} // namespace Test
工厂.cpp
#include "common.hpp"
namespace Test {
class Impl {
public:
static A getA(int val) { return A(new int{val}); }
static B getB(int val) { return B(new int{val}); }
};
A Factory::getA(int val) { return Impl{}.getA(val); }
B Factory::getB(int val) { return Impl{}.getB(val); }
} // namespace Test
主.cpp
#include <iostream>
#include "common.hpp"
int main() {
Test::Factory factory;
std::cout << factory.getA(1).plus_one() << std::endl;
std::cout << factory.getB(1).plus_two() << std::endl;
return 0;
}
输出:
$ g++ A.cpp B.cpp Factory.cpp main.cpp -o test
$ ./test
2
3
不可以,不允许相同的类类型具有不同的定义。您的程序直接违反了 ODR,并表现出未定义的行为。
[basic.def.odr]
6 类类型可以有多个定义,[...] 一个程序,前提是每个定义出现在不同的定义中 翻译单元,前提是定义满足以下条件 要求。给定在多个中定义的名为 D 的实体 翻译单元,然后
- D的每个定义应由相同的令牌序列组成;和
- [...]
[...]如果 D 的定义满足所有这些要求,则 行为就像D有一个单一的定义。如果 D的定义不满足这些要求,那么行为 未定义。
您的两个定义在令牌序列上已经非常明显地不同,因此 ODR 的条件没有得到支持。
相关文章:
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 为什么不同类型层次结构的指针之间的dynamic_cast定义得很好?
- 是否允许类在程序中的不同翻译单元之间具有不同的定义?
- 定义类模板构造函数的两种方法之间的区别
- 在两个.cpp文件之间定义全局类/结构指针
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- 在类内定义的友元函数与类外定义的友元函数的查找规则之间的差异
- 如何在自定义 LLVM 传递之间正确传递数据结构
- 是std::memcpy在不同的可复制类型之间的未定义行为
- C++声明和定义之间拆分默认参数值
- #define DATA 10 和 # (如果定义了 DATA)之间的差异
- 重复符号 --- 定义和声明之间的差异
- 定义整数之间的特殊划分
- 将类类型成员定义为公共和私有之间有什么区别?
- pimpl和定义类别的.cpp文件之间的区别
- Android NDK 中的预构建工具链和自定义工具链编译器之间的差异
- 生成一组随机的 x,y,z 数,它们之间和定义的限制之间具有最小差异
- Arduino在定义语句之间切换
- 版本之间定义的实现
- 使用模板在不同类型之间定义操作