c++ 模板化抽象基类数组,不违反严格别名规则

Posted

技术标签:

【中文标题】c++ 模板化抽象基类数组,不违反严格别名规则【英文标题】:c++ array of templated abstract-base-class without breaking strict-aliasing rule 【发布时间】:2018-11-30 18:07:16 【问题描述】:

在不违反严格别名规则的情况下,创建从抽象模板基类派生的对象数组的最佳方法是什么?每个派生对象都会以不同的方式定义基类的模板参数,但只能通过常量枚举值。这是一个例子

enum  BlaEnum

  Bla1,
  Bla2,
  Bla3
;

template <class T, BlaEnum bla = Bla1>
class A

public:
   virtual void Foo() = 0;
   T att;
   BlaEnum bll;
;

class B : public A<int, BlaEnum::Bla2>

public:
   void Foo() override;
;

 class C : public A<int, BlaEnum::Bla3>

public:
   void Foo() override;
;

int main(void)


  B b;
  C c;

  //violates strict-aliasing rule
  A<int>* BaseArr[2] =  (A<int>*)&b,(A<int>*)&c ;


【问题讨论】:

具有不同实际类型参数的实例是不同的类,彼此无关(通过继承或任何其他关系),尽管有共同的模板名称。 【参考方案1】:

这里的问题是class B : public A&lt;int, BlaEnum::Bla2&gt;class C : public A&lt;int, BlaEnum::Bla3&gt; 派生自彼此不兼容的不同A。这些类中的每一个都会导致一个新模板类的实例化(它们都不兼容A&lt;int&gt;)。

为了拥有有效的公共基础,您需要一个与派生类在任何模板参数(或者是非模板类)上都没有区别的基类。 修改您的示例,例如:

template <class T>
class Base 

public:
    virtual void Foo() = 0;
;

template <class T, BlaEnum bla = Bla1>
class A : public Base<T>

public:
   T att;
   BlaEnum bll;
;
// B and C are unchanged
int main()

  B b;
  C c;
  // Array of pointers to common base class
  Base<int>* BaseArr[2] =  &b,&c ;

另一个注意事项:C 风格的数组不是一个好习惯,您应该更喜欢 std::array(或 std::vector)和智能指针而不是原始指针

【讨论】:

以上是关于c++ 模板化抽象基类数组,不违反严格别名规则的主要内容,如果未能解决你的问题,请参考以下文章

这真的违反了严格的别名规则吗?

这真的违反了严格的别名规则吗?

如何投射 so​​ckaddr_storage 并避免违反严格的别名规则

C++ 构建警告:取消引用类型双关指针将破坏严格别名规则

严格别名规则“-fstrict-aliasing”和“-fno-strict-aliasing”及类型双关

C++函数模板和普通函数的调用规则