12

私が使用しているいくつかのレガシーコードには、次の定義があります。

struct VlanData
{
    uint16_t mEtherType;
    uint16_t mVlanId;
};

この構造体に新しいメンバーを追加したい:

struct VlanData
{
    uint16_t mEtherType;
    uint16_t mVlanId;
    uint8_t mVlanPriority; // New member
};

ただし、VlanDataレガシーコードでは、の使用にかなりの一貫性がありませんでした。

構築時に初期化されていません:

VlanData myVlans;
myVlans.mEtherType = 0x8100;
myVlans.mVlanId = 100;

初期化された値:

VlanData myVlans = { 0x8100, 100 };

私がやりたいのは、多くのコードを更新せずに、レガシーコードで`mVlanPriority'が自動的に0に設定されるようにする安全な方法を考え出すことです。

レガシーコードを変更して、次のようにすべてのメンバーを値初期化できることを理解しています。

VlanData myVlans = {};

しかし、このコードをすべて更新する必要はありません。このようなデフォルトのコンストラクターを作成すると、次のことが役立つと思います。

VlanData()
: mEtherType(0),
  mVlanId(0),
  mVlanPriority(0)
{}

しかし、これはPOD構造体の性質も破壊します。

だから私はいくつかの質問があると思います:

  1. mVlanPriorityレガシーコードを更新せずにレガシーコードで0に設定されて いることを確認できる安全な方法はありますか?
  2. PODこれがタイプでなくなった場合、クラスのどのような使用が中断されますか?
4

3 に答える 3

5
struct VlanData {
    struct P
    {
        uint8_t operator=(uint8_t v) { mVlanPriority = v; }
        uint8_t mVlanPriority; P() { mVlanPriority = 0; };
    };
    uint16_t mEtherType;
    uint16_t mVlanId;
    P mVlanPriority;
 };

他の種類の演算子を定義し、必要に応じて型変換関数を追加します。

例えば:

int main(int argc, char** argv)
{
    VlanData myVlans0 = { };
    VlanData myVlans = { 0x8100, 100 };
    myVlans.mVlanPriority = 10;
}
于 2011-07-19T06:50:19.097 に答える
1

レガシー コードを更新せずに、レガシー コードで mVlanPriority が 0 に設定されていることを確認できる安全な方法はありますか?

いいえ、現在の標準には標準的な方法はありません。コンストラクターが必要です。

これが POD タイプではなくなった場合、クラスのどのような使用法が壊れるでしょうか?

@junjanes がコメントで述べたように、メンバーを括弧で初期化しようとすると、コードが壊れます。

編集:あなたの問題に対処するために、私はお勧めします

struct VlanData
{
  uint16_t mEtherType;
  uint16_t mVlanId;
  uint8_t mVlanPriority; // New member

  VlanData(uint16_t ether, uint16_t id, uint8_t priority = 0) :
           mEtherType(ether), mVlanId(id), mVlanPriority(priority)
  {}
};

これで、新しい変数が に初期化され、コンパイル エラーを修正するために入力する0必要が非常に少なくなります。

変化する、

VlanData myVlans = { 0x8100, 100 };

に、

VlanData myVlans( 0x8100, 100 );
于 2011-07-19T06:26:32.477 に答える
0

私はc++0xの専門家ではありませんが、クラスの導入により、厳格性のpod保証が緩和されたことは知っています。コンストラクターを持つクラスはそうではありませんが、そうであると私は信じているので、コンパイラーが新しい標準のこの側面と互換性があるかどうかを確認する価値があるかもしれません。あなたが抱えている問題は、でかなり修正されたと思います。c++0xstandard-layoutpodstandard-layoutc++0x

また 、c++ 0xでは標準レイアウトクラスの中括弧による初期化も許可されていると思います。このウィキペディアの記事のInitializer listsUniform initializationセクションを参照してください。

標準レイアウトクラスの修正で何が修正されるかを調べると、現在の標準の非ポッドタイプで何が壊れるかについてかなり良いリストが得られます。たとえば、reinterpret_castは、ポッド以外のタイプのc ++ 03では安全ではありませんが(配置が正しくない可能性があります)、標準レイアウトクラスのc++0xでは安全です。

要するに、あなたの欲求不満はよく認識されており、おそらく新しい標準で解決されていると思いますが、現在の標準でそれらすべてを修正することは不可能だと思います。

私のアプローチは、レガシーコードをそのままにして、クラスの新しいバージョンにゆっくりと移行することです。

namespace version_1_1
{
  struct VlanData
  {
      uint16_t mEtherType;
      uint16_t mVlanId;
      uint8_t mVlanPriority; // New member
  };

  vlanData 
  convert_VlanData( ::VlanData const& v)
  {
     VlanData v2 = {v.mEtherType,v.mVlanId, 0};
     return v2;
  }
}

そして、いつ何を使用しているかを明確かつ明確にし、必要なときに物事を移行します。

于 2011-07-19T06:37:58.777 に答える