私は VS2008 でこのコードを使用しようとしました (そして、サンプルにあまりにも多くのコンテキストが含まれている可能性があります...):
class Base
{
public:
void Prepare() {
Init();
CreateSelectStatement();
// then open a recordset
}
void GetNext() { /* retrieve next record */ }
private:
virtual void Init() = 0;
virtual string CreateSelectStatement() const = 0;
};
class A : public Base
{
public:
int foo() { return 1; }
private:
virtual void Init() { /* init logic */ }
virtual string CreateSelectStatement() { /* return well formed query */ }
};
template<typename T> class SomeValueReader : protected T
{
public:
void Prepare() { T::Prepare(); }
void GetNext() { T::GetNext(); }
T& Current() { return *this; } // <<<<<<<< this is where it is interesting
SomeValue Value() { /* retrieve values from the join tables */ }
private :
string CreateSelectStatement() const
{
// special left join selection added to T statement
}
};
void reader_accessAmemberfunctions_unittest(...)
{
SomeValueReader<A> reader();
reader.Prepare();
reader.GetNext();
A a = reader.Current();
int fooresult = a.foo();
// reader.foo() >> ok, not allowed
Assert::IsEqual<int>( 1, fooresult );
};
これは期待どおりに動作します。つまり、"A" メンバー関数にアクセスでき、fooresult は 1 を返します。ただし、unittest 関数の最後でオブジェクトが削除されると、例外がスローされます。
System.AccessViolationException: 保護されたメモリを読み書きしようとしました。これは多くの場合、他のメモリが破損していることを示しています
Current() 関数の戻り値の型を次のように変更すると:
T* Current()
{
T* current = dynamic_cast<T*>(this);
return current;
}
その後、すべて問題なく、単体テストはアクセス違反なしで終了します。最初の Current() 実装の何が問題だったのか誰か教えてもらえますか? ありがとう、ブーシェ。