首页 > 解决方案 > c++ 模板化抽象基类数组,不违反严格别名规则

问题描述

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

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 };

}

标签: c++arraysinheritancestrict-aliasingtemplate-classes

解决方案


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

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

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(or std::vector) 和智能指针而不是原始指针


推荐阅读