0

次のコードを検討してください。

Base b;
if (something)
    b = DerivedA();
else
    b = DerivedB();

このような場合、「スライス」が発生することはよく知られています。C++ では、基本型の変数に派生型のオブジェクトを割り当てることはできません。オブジェクトは、基本型で定義されていないものから「スライス」されます。(そのようなことをしたい場合は、ポインターまたは参照を使用する必要があります)。

この本当の理由を理解したい。Baseつまり、変数がDerivedオブジェクトをスライスせずに保持できない理由です。

この理由は、Baseオブジェクトとオブジェクトが同じサイズではない可能性があるためであり、オブジェクト全体を変数Derivedに格納できることを保証できないためだと思います。aは 4 バイトを使用する場合がありますが、aは 7 バイトです。そのため、基本型のサイズに合わせて派生オブジェクトを常にスライスすることにしました。DerivedBaseBaseDerived

ポインターはすべて同じ量のメモリを占有するため、ポインターを使用してこれを行うことができます

この仮定は正しいですか?そうでない場合、スライスの実際の理由は何ですか?

4

2 に答える 2

2

いいえ。あなたの例では、スライスの理由が異なります。

の行Base b;では、スタック上の型のオブジェクトにスペースを割り当て、Baseその既定のコンストラクターを既に呼び出しています。したがって、if-statementの各ブランチで、への代入bが行われます。これは、代入演算子 (通常は signature を使用) によって実現されますBase::operator=(const Base&)。この演算子をオーバーロードしない場合、そのデフォルトのセマンティクスはフィールドごとのコピーです。引数の型がBase(or const Base&) であるためBase、右側の -fields のみが表示されることに注意してください!

オブジェクトに含まれるすべての情報をオブジェクトに格納する何らかの方法がある仮定すると(これはありそうもないことですが)、代入演算子を as としてオーバーロードし、独自の代入セマンティクスを実装すると、上記は完全に正常に機能します。DerivedABaseBase::operator=(const DerivedA&)

于 2014-10-16T22:07:08.610 に答える
2

問題は、コピーと移動のセマンティクス (コピー コンストラクター、コピー代入など) にあります。要素のコピーを取得していますが、すべての要素がコピーされるわけではありません。ベースポインタがあれば問題ありません。

完全に設定された DerivedA オブジェクトがあり、それをローカル スタック基本型に割り当てた場合、コピー割り当てが使用され、派生要素の値は破棄されます。

コピー コンストラクターを記述するときは、考慮してください。現在のクラスのメンバー以外に追加の作業はありますか? 現在のクラスから派生したものと、何をすべきかをどのように知ることができますか? そうしようとするのは非常に悪いことです。

class BaseType
{
private:
    int m_i;

public:
    explicit BaseType(BaseType const & other) // copy ctor
    {
        m_i = other.m_i;   // bitwise copy or memberwise copy will suffer the same issue
        // what else is there to do?  
        // BaseType has no knowledge of any other members
    }

    BaseType & BaseType::operator=(BaseType const & other)  // copy assignment
    {
        m_i = other.m_i;
        // what else is there to do?  
        // BaseType has no knowledge of any other members
    }
};

ビットごとのコピー ( for std::is_trivially_copyable<T>) でも、サイズは BaseType になり、ご指摘のとおり、必要以上に小さくなり、データが切り捨てられます。

お役に立てれば。

于 2014-10-16T22:02:50.187 に答える