1

編集:完全に言い直された質問:以下の回答:

派生型を基本型への参照として渡すときに問題が発生します。参照されたオブジェクトは、Derived から Base にキャストされる前後にデータがクリア/再初期化されているようです。

パラメータを Base オブジェクトへの参照として受け入れる関数に Derived インスタンスを渡すと (Derived -> Base&)、参照された Base インスタンスは、値として渡されない限り、Derived オブジェクトに対してメモリ内で一貫性を保つと考えました。

「読み取り専用」と見なされるデータの状態である Base クラスがあります。

class ReadonlyText
{
protected:
   int m_Length;
   char* m_String;
public:
   ReadonlyText() m_Length(0), m_String(0) {} // a null base
   ReadonlyText(const char* str) : m_Length(0), m_String(str)
   {
       do
       {
           m_Length++;
       }while(*ptr++);
   }
   ReadonlyText(const ReadonlyText& copy) : m_Length(copy.m_Length), m_String(copy.m_String)
   {
   }
   virtual ~Readonly() {};

   ... virtual nonsense
};  // lets not forget the semicolon

これで、書き込み可能な Derived クラスができました。

class Text
{
public:
    Text() : m_Length(1), m_String(Memory::New<char>(m_Length)) {}
    Text(const ReadonlyText& copy) : m_Length(copy.m_Length), m_String(Memory::New<char>(m_Length))
    {
        for(whole i = 0; i < m_Length; ++i)
            m_String[i] = copy.m_String[i];
    }
    Text(const Text& copy) : m_Length(copy.m_Length), m_String(Memory::New<char>(m_Length))
    {
        for(whole i = 0; i < m_Length; ++i)
            m_String[i] = copy.m_String[i];
    }

    virtual ~Text()
    {
         if((m_Length != 0 && m_String != null<char>::value)) 
         {
              Memory::Delete<Char>(m_String);
              m_Length = 0;
              m_String = null<Char>::value;
         }
    }

    // operator==(ReadonlyText&)
    // operator!=(ReadonlyText&)
    // operator==(Text&)
    // operator!=(Text&)
    // operator=(Text&)
    // operator=(ReadonlyText&)
    // I don't have time to format all these functions for best visibility in SO, 
    // I assure you that all these functions are implemented properly

    // THE PROBLEM occurs in any function with ReadonlyText&, say:
    Text operator+(const ReadonlyText& rhs)
    {
        //...
        // Before the function begins, 'rhs.m_String' == 0x0
        // see case below 
    }
};

// ...

int main(...)
{
    Text t1 = Text("hello");
    Text t2 = Text("world");

    // in the debugger, at this point, both t1 && t2 '.m_String' is valid
    // as "hello" and "world" respectively
    // but when stepping into:

    Text t3 = t1 + t2; // the function described above...

    // ...which is t1.operator+(t2) // where t2 is passed as ReadonlyText&
    // the debugger shows:
    // t1.m_String == "hello"
    // t2.m_String == 0x0   -- this should be "world"

    // since no copy construction is occuring, (passing as reference), then
    // the data should be consistent with the derived type, right?

}

operator+ で、「rhs.m_String」にアクセスしようとしましたが、これは「world」に評価されますが、何らかの理由で、参照として渡されるのではなく、新しい ReadonlyText としてインスタンス化されていますか??

さらに、プログラムはメッセージでクラッシュしません。セグメンテーション違反やエラーはありません。代わりに、メインの終わりまでアプリケーションがスムーズに実行されたかのように、完全に終了しますか?

ここで説明する以上のことはありません。Memory::New と Memory::Delete はメモリ操作 (new と delete) をカプセル化し、New がテンプレートの型名のサイズと指定された長さに基づいてポインターを返すようにします。削除は、ポインターの適切な破棄を保証するだけです。null は、型名の一貫した null 値を保証する構造です。

//class Memory:

template<typename T> static T* New(whole length = 1)
{
    return (T*)(operator new (length * sizeof(T)));
}
template<typename T> static void Delete(T* pointer)
{
    operator delete (pointer);
}

// null struct
template<typename T>
struct null
{
    static constexpr T* value = 0x0;
}

本当の問題:

<_< クラス階層を再設計するときに、派生メンバー (m_Length と m_String) を削除するのを忘れていました。したがって、Derived インスタンスには、Base メンバーをマスクするメンバーが含まれていました。簡単に言えば、何かが意味をなさない場合、それはおそらくあなたのせいです:

class Base
{
    ...
protected:
    int m_Length;
    char* m_String;
};

class Derived : public virtual Base
{
    ...
protected:  // xD WTH was I hoping to do here???
    int m_Length;
    char* m_String;
};

マスキングを防ぐ継承用のコンパイラ機能があるはずですが、それまでは注意してください...ただ注意してください。私を助けようとした皆さん、そして手を引いた人たちに感謝します。

4

1 に答える 1

2

これが実際のコードの一部である場合、派生クラスにエラーがあると思われます。クラスにm_Data属しているため、Baseクラスで直接初期化することはできず、クラスDerivedに直接アクセスできないため、まったくアクセスできません、次に、あなたにもメンバーがいて、そのメンバーがof を非表示にしていると仮定します。したがって、デバッガーに表示されるのはであり、関数に表示されるのはです。これは、デフォルトのコンストラクターを使用して初期化されるためですprivateBasem_DataDerivedm_DataBasem_DataDerivedm_DataBasenullptrBase

于 2012-10-18T21:55:14.810 に答える