这是一个可能的解决方案。它总是选择具有最高对齐操作者在给定的层次:
#include <exception>
#include <iostream>
#include <cstdlib>
// provides operators for any alignment >= 4 bytes
template<int Alignment>
struct DeAllocator;
template<int Alignment>
struct DeAllocator : virtual DeAllocator<Alignment/2> {
void *operator new(size_t s) throw (std::bad_alloc) {
std::cerr << "alignment: " << Alignment << "\n";
return ::operator new(s);
}
void operator delete(void *p) {
::operator delete(p);
}
};
template<>
struct DeAllocator<2> { };
// ........... Test .............
// different classes needing different alignments
struct Align8 : virtual DeAllocator<8> { };
struct Align16 : Align8, virtual DeAllocator<16> { };
struct DontCare : Align16, virtual DeAllocator<4> { };
int main() {
delete new Align8; // alignment: 8
delete new Align16; // alignment: 16
delete new DontCare; // alignment: 16
}
它是基于优势的规则:如果在查找的歧义,和模糊性的派生名称和虚拟基础之间类,而是派生类的名称。
问题是上升的原因DeAllocator<I>
继承DeAllocator<I/2>
。答案是因为在给定的层次结构中,类可能会有不同的对齐要求。想像一下,IBase
没有对准要求,A
有8个字节的要求和B
具有16个字节的要求,并且继承A
:
class IBAse { };
class A : IBase, Alignment<8> { };
class B : A, Alignment<16> { };
Alignment<16>
和Alignment<8>
都暴露一个operator new
。如果你现在说new B
,编译器会寻找operator new
在B
,并会找到功能:
// op new
Alignment<8> IBase
^ /
\ /
\ /
// op new \/
Alignment<16> A
\ /
\ /
\/
B
B -> Alignment<16> -> operator new
B -> A -> Alignment<8> -> operator new
因此,这将是暧昧,我们将无法编译:这些都不隐藏其他一。但是,如果你现在从Alignment<8>
继承Alignment<16>
实际上并A
和B
继承它们实际上,在Alignment<8>
的operator new
将被隐藏:
// op new
Alignment<8> IBase
^ /
/\ /
/ \ /
// op new/ \/
Alignment<16> A
\ /
\ /
\/
B
这个特殊的隐藏规则(也称为主导地位规则),但只有工作,如果所有的Alignment<8>
对象都是一样的。因此,我们总是继承几乎:在这种情况下,在任何给定的类层次结构中存在的只有一个Alignment<8>
(或16,...)对象。
也许你可以为具有特殊对齐要求的少数对象使用不同的IBase(IBase16?)。 – 2010-03-02 21:32:08
你甚至可以使这个基类(IBase16,IBase32)模板化,所以你可以使用IBase。 –
Patrick
2010-03-02 21:35:15
您可以在64字节的边界上对齐。 :) – Bill 2010-03-02 21:42:52