1

既存のコード:

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

私の要件:ここで、Aからクラスを派生させる必要があり、派生クラスでは、x1、x2、およびx3のビットサイズを変更する必要があります。

どうすればこれを行うことができますか?ご協力いただきありがとうございます !

編集

私は約のクラス(Aとしましょう)を持っています。7〜8個のユニオン(それぞれがHWレジスタを表す)、および約20個(約)の関数。これらの関数のほとんどは、これらの共用体のインスタンスを作成し、ビット(私の例では、x1、x2、x3など)を使用します。

今、私の要件は、95%の機能が同じである新しいハードウェアのコードを追加することです。変更には、レジスタのビットサイズの変更、および一部の機能の変更が含まれます。したがって、20の関数のうち、実装を変更するには、少なくとも5つの関数を変更する必要があります。これが、継承を選択してこれらの関数をオーバーライドする理由です。

残りの15個の機能は、ビットサイズの変更のみが変更されます。したがって、これらの関数をオーバーライドしたくはありませんが、基本クラスの関数を使用します。ただし、レジスタ(ユニオン)のビットサイズは変更する必要があります。それ、どうやったら出来るの?

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

与えられたデザインでは、それを解決することはできません。問題は、メソッドを派生させてオーバーライドすることはできますが、データメンバーをオーバーライドすることはできず、派生クラスでオーバーライドされないメンバーは、実行しているのとまったく同じ方法でフィールドにアクセスするため、結果として次のようになります。さまざまな場所でさまざまなサイズを使用します。

ランタイムポリモーフィズム

設計についてはあまり考えていませんが、最初の単純なランタイムアプローチは、既存のすべてのコードをリファクタリングして、フィールドに直接アクセスする代わりに、アクセサー(セッターゲッター)を使用してアクセスし、引数をにマップすることです。ストレージタイプ。これらのアクセサーをオーバーライドすることができ、関数は各ビットフィールドの正確なサイズに依存しません。マイナス面として、アクセサーを仮想化することは、パフォーマンスインスタンスが存在することを意味するため、検討する必要があります。

コンパイル時(または静的)ポリモーフィズム

クラスをリファクタリングして、ユニオンの型を引数として取るテンプレートにすることができます。このようにして、現在のデザインの派生クラスに含まれるものとは異なるユニオンを使用してテンプレートをインスタンス化できます。新しいメンバー関数の追加(メンバー関数を使用する場合)はそれほど単純ではなく、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 に答える