2016-09-08 6 views
0

混乱しているタイトルは申し訳ありません。私は自分の問題をより良く表現する方法がわからない。テンプレートパラメータが導出されるが、キャストが動作していないのはなぜC++のテンプレートと基底クラスとサブクラスをテンプレートパラメータとして使用してキャスト

template<class T> 
class TmpClass 
{}; 

class Base 
{}; 

class Child : public Base 
{}; 

int main() 
{ 
    typedef TmpClass<Base*> A; 
    typedef TmpClass<Child*> B; 

    A a; 
    B b; 
    A* ap = &b; //this does not work 
} 

次のコードを見てください?

+1

に分類されます。一方、 'Child'は' Base'から派生するかもしれません。 'TmpClass 'は 'TmpClass ' – Hayt

+0

でもOKですがTmpClass はTmpClassには完全に適合していません? – Naibaf

+0

はい、テンプレートは2つの異なるクラスを生成します。そして、あなたがTをどのように使っているかによって、暗黙的に変換可能な場合には、多くのことが起こり、未定義の動作が多く発生します。 – Hayt

答えて

1

これは2つの異なるクラスを生成するためです。

template<class T> 
struct TmpClass 
{ 
    T t; 
    double d; 
}; 

struct Base 
{ 
    int i; 
}; 

struct Child : public Base 
{ 
    int i2; 
}; 

これは本当に基本的なものとも、これはちょうど発生する可能性の問題のために簡略化されているなどの仮想関数を持つより雑然と次のようになります。次のことを前提とします。

あなたは今、彼らはこのように見えるのクラス(トンは彼の名前は完全に私によって構成されています)

struct _internal_TmpClass_Base 
{ 
    Base t; 
    double d; 
}; 

struct _internal_TmpClass_Child 
{ 
    Child t; 
    double d; 
}; 

をインスタンス化するとき事がある:

Baseのサイズはsizeof(int)です。 Childのサイズは2*sizeof(int)

dにTmpClassでアクセスしたい場合は、完全に異なるメモリの場所にあります(テンプレートによって異なります)。 TmpClass<Child>は、Child(2 * int)のサイズの後の位置にdの位置にあります。今度はTmpClass<Base>にキャストし、dにアクセスしたい場合は、Base(1 * int)のサイズがChildでないことがメモリ内にあるとみなします。そしてあなたはあなたが意図していない記憶を読み書きします。

これらのものは、2つの異なる無関係なクラスであるため、通常、「未定義の動作」

+0

ありがとう:)今私はポイントを得た。 – Naibaf

+0

もう少し詳細を表示する方が良いと思いました。そして、これは物事がうまくいかない例の一つです。 – Hayt

関連する問題