1

The existing code:

typedef unsigned int uint;
Class A
{
union xReg
    {
        uint allX;
        struct
        {
            uint x3      : 9;
            uint x2      : 9;
            uint x1      : 14;
        }__attribute__((__packed__)) __attribute__((aligned(4)));
    };
};

My requirement: Now, I need to derive a class from A, and and in the derived class, the bit sizes of x1, x2 and x3 has to change.

How do i do this ? Thanks for your help !

EDIT

I have a class (lets say A) with approx. 7-8 unions (each representing HW register), and around 20 (approx.) functions. Most of these functions create instances of these unions, and use the bits (x1, x2, x3 etc in my example).

Now, my requirement is to add code for a new hardware which has 95% of functionality same. The changes include the change in register bit sizes, and some functionality change. So, among 20 functions, atleast 5 functions I need to change to change the implementation. This is the reason for me to select inheritance and override these functions.

The rest 15 functions, only change is the bit size changes. So, I dont want to override these functions, but use the base class ones. But, the bit sizes of the registers (unions) should change. How do I do that?

4

3 回答 3

3

您不能在 C++ 的派生类中更改位域长度。

但是,您可以尝试使用 bit_field 长度参数化您的类。

template <size_t N1, size_t N2, size_t N3 = 32 - N1 - N2>
struct myStruct
{
    uint bitField1 : N1;
    uint bitField2 : N2;
    uint bitField3 : N3;
};

现在您可以使用您希望的任何 N1、N2、N3 来实例化该结构,例如:

myStruct<9, 9> s;
于 2011-07-01T17:25:49.540 回答
1

使用给定的设计,您无法解决它。问题是,虽然您可以派生和覆盖方法,但不能覆盖数据成员,派生类中未覆盖的成员将以完全相同的方式访问该字段,结果是您将在不同的地方使用不同的尺寸。

运行时多态性

我对设计没有太多考虑,但第一个简单的运行时方法将重构所有现有代码,以便通过访问器(settergetter)而不是直接访问字段,并将参数映射到存储类型。您将能够覆盖这些访问器,并且这些函数将不依赖于每个位域的确切大小。不利的一面是,访问器是虚拟的意味着会有一个性能实例,所以你可以考虑

编译时(或静态)多态性

您可以重构该类,使其成为一个将联合类型作为参数的模板。这样,您可以在当前设计中的派生类中使用不同的联合来实例化模板。添加新成员函数(如果您想使用成员函数)不会那么简单,您最终可能不得不使用 CRTP 或其他方法来创建实现的基础,同时允许您通过专业化对其进行扩展。

template <typename R>
class A
{
   R xReg;
public:
   unsigned int read_x1() const {
       return xReg.x1;
   }
// rest of implementation
};

union xReg1 {
   unsigned int all;
   struct {
      unsigned int x3 : 9;
      unsigned int x2 : 9;
      unsigned int x1 : 14;
   };
};
union xReg2 {
   unsigned int all;
   struct {
      unsigned int x3 : 8;
      unsigned int x2 : 9;
      unsigned int x1 : 15;
   };
};

int main() {
   A< xReg1 > initial;
   std::cout << initial.access_x1() << std::endl;

   A< xReg2 > second;
   std::cout << second.access_x1() << std::endl;
}
于 2011-07-01T21:30:43.377 回答
0

鉴于您的附加问题陈述,Armen 建议的变体可能适用。听起来好像您在这里不需要实际的继承,只是重用一些公共代码的某种方式。

例如,您可能根本不需要成员函数。

template<typename reg>
union hardware_register {
    unsigned all;
    struct {
        unsigned i : reg::i;
        unsigned j : reg::j;
        unsigned k : reg::k;
    };
};

template<typename hardware>
void print_fields(const hardware& hw) {
   cout << hw.i << " " << hw.j << " " << hw.k << endl;
}

//this method needs special handling depending on what type of hardware you're on
template<typename hardware>
void print_largest_field(const hardware& hw);

struct register_a {
    static const unsigned i = 9;
    static const unsigned j = 4;
    static const unsigned k = 15;
};

struct register_b { 
    static const unsigned i = 4;
    static const unsigned j = 15;
    static const unsigned k = 9;
};

template<>
void print_largest_field<register_a>(const register_a& a) {
    cout << a.k << endl;
}

template<>
void print_largest_field<register_b>(const register_b& b) {
    cout << b.j << endl;
}

int main() {
    hardware_register<register_a> a;
    hardware_register<register_b> b;
    print_fields(a);
    print_fields(b);
    print_largest_field(a);
    print_largest_field(b);
}

或者,您可以将所有常见功能包装到模板化基类中。您从该基类派生,并实现您需要的任何特殊行为。

template<typename HW> 
struct base {
    void print_fields {
        cout << hw.i << hw.j << hw.k << endl;
    };
private:
    HW hw;
};

struct hw_a : base<register_a> {
    void print_largest_field {
        cout << hw.k << end;
    }
};

struct hw_b : base<register_b> {
    void print_largest_field {
        cout << hw.j << end;
    }
};

您可以为不同类型的寄存器提供多个模板参数,或扩展底层特征结构,使其一次定义多个寄存器。

于 2011-07-01T21:58:11.360 回答