7

組み込みプログラミングには C++ を使用しています。

厳密に定義された (つまり、バイトごとに) クラス型を実装する必要があると仮定すると、その型のオブジェクトをバイト レベルで変更せずに、コンストラクターやその他の非仮想メソッドをクラス型に追加できますか? つまり、追加のデータが追加されないと仮定できますか?

RTTIがオフになっていると仮定します。

C++ 標準でこれが定義されているかどうかを確認したいと思います。

4

4 に答える 4

8

はい、コンストラクターおよび/または非仮想メソッドのみを追加する場合、元のクラスと新しいクラスはレイアウトの互換性があるため、クラスのサイズまたはレイアウトは変更されません (9.2 クラス メンバー [class.mem] #17 )、ただし、それらが標準レイアウト クラスである場合に限ります

標準レイアウト クラスは次のように定義されます。

9 クラス [クラス]

標準レイアウト クラスは、次のようなクラスです。

— 非標準レイアウト クラス (またはそのような型の配列) 型または参照型の非静的データ メンバーを持たない、

— 仮想関数 (10.3) も仮想基本クラス (10.1) もありません。

— すべての非静的データメンバーに対して同じアクセス制御 (条項 11) を持ちます。

— 非標準レイアウトの基本クラスはありません。

— 最も派生したクラスに非静的データ メンバーがなく、非静的データ メンバーを持つ基本クラスが最大で 1 つあるか、または非静的データ メンバーを持つ基本クラスがない。

— 最初の非静的データ メンバーと同じ型の基本クラスがありません。

于 2012-12-13T14:10:26.540 に答える
7

いいえ、そうではありません。

C++11 については、次のように述べていsizeofます。

[C++11: 5.3.5/2]:[..] 参照または参照型に適用すると、結果は参照型のサイズになります。クラスに適用すると、結果は、そのタイプのオブジェクトを配列に配置するために必要なパディングを含む、そのクラスのオブジェクトのバイト数になります。最も派生したクラスのサイズはゼロ (1.8) より大きくなければなりません。基本クラスのサブオブジェクトに適用sizeofした結果は、基本クラスの型のサイズになります。配列に適用すると、結果は配列内の合計バイト数になります。これは、n要素の配列のサイズが要素のサイズのn倍であることを意味します。

...そしてそれはそれについてです。「そのタイプのオブジェクトを配列に配置するために必要」が何を意味するかを指定せず、代わりにそれをターゲットABIに任せます。

以前のホーム(grr)から最近姿を消した Itanium ABI は、私の記憶が正しければ、あなたが探している種類の保証を行いますが、それは C++ の保証と同じではありません。まったく同じではありません。

コンパイラ固有のパッキング/アライメント オプションを使用して、データ メンバーを処理できます。ただし、仮想機能によるスペースの増加は制御できません。非仮想関数用にスペースが追加されることは期待できませんが、これも「保証」されていません。

static_assert(sizeof T == x, "T needs to be x bytes wide")コードの変更によって何らかの仮定が破られた場合はいつでも検出できます。これはあなたが得る最高のものです。

于 2012-12-13T13:50:10.100 に答える
5

C++03 以前では、いいえ。レイアウトに関しては、絶対に保証するものではありません。C++11 にはレイアウト互換という概念がありますが、どこまで対応できるかはわかりません。クラスに非仮想関数を追加しても、レイアウトの互換性が損なわれないことを願っています。一方、組み込みプログラミングと RTTI のオフについて言及しています。おそらく、標準ではなく、コンパイラによって保証されている他の多くのことを当てにしているでしょう。(たとえば、RTTI をオフにする機能。) それを考えると、コンパイラによる保証を探すことをお勧めします。組み込みシステムを対象とするほとんどのコンパイラは、生成するレイアウトの詳細な説明を提供していると思います。そこから進むことができます。

于 2012-12-13T14:10:01.893 に答える
1

この保証は、ワーキング ドラフト C++、n3242、2011-02-28から導き出すことができます。

9.2 クラス メンバ
18 2 つの標準レイアウト構造体 (条項 9) 型は、同じ数の非静的データ メンバを持ち、対応する非静的データ メンバ (宣言順) がレイアウト互換型 (3.9) を持っている場合、レイアウト互換性があります。 .

これはデータメンバーのみについて話しているので、2 つのクラス

struct A {
int d1;
float d2;
void f();
};

struct B {
int e1;
float e2;
int g() const;
double h();
};

レイアウト互換である必要があります。

そして、標準レイアウトクラスとは

9 クラス
7 標準レイアウト クラスは、次のようなクラスです。
— 非標準レイアウト クラス (またはそのようなタイプの配列) または参照の非静的データ メンバーを
持たない — 仮想関数 (10.3) も仮想関数も持たない基本クラス (10.1)
— すべての非静的データ メンバーに対して同じアクセス制御 (条項 11) を
持つ — 非標準レイアウトの基本クラス
を持たない — 最も派生したクラスに非静的データ メンバーを持たない、および非静的データ メンバーを持つ最大 1 つの基本クラス、または非静的データ メンバーを
持つ基本クラスがなく、かつ — 最初の非静的データ メンバーと同じ型の基本クラスがない.108

于 2012-12-13T14:44:46.447 に答える