誰もこの予期しない動作を説明できますか?基底クラスctorから派生クラスの仮想関数を呼び出すことが予期せず可能です
前提
私はメンバーstd::thread
変数を含むクラスのスレッドを作成しました。スレッドのctorは、メンバstd::thread
を構築して、(基本クラスによって実装される)純粋仮想関数を呼び出す静的関数へのポインタを提供します。
コード
#include <iostream>
#include <thread>
#include <chrono>
namespace
{
class Thread
{
public:
Thread()
: mThread(ThreadStart, this)
{
std::cout << __PRETTY_FUNCTION__ << std::endl; // This line commented later in the question.
}
virtual ~Thread() { }
static void ThreadStart(void* pObj)
{
((Thread*)pObj)->Run();
}
void join()
{
mThread.join();
}
virtual void Run() = 0;
protected:
std::thread mThread;
};
class Verbose
{
public:
Verbose(int i) { std::cout << __PRETTY_FUNCTION__ << ": " << i << std::endl; }
~Verbose() { }
};
class A : public Thread
{
public:
A(int i)
: Thread()
, mV(i)
{ }
virtual ~A() { }
virtual void Run()
{
for (unsigned i = 0; i < 5; ++i)
{
std::cout << __PRETTY_FUNCTION__ << ": " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
protected:
Verbose mV;
};
}
int main(int argc, char* argv[])
{
A a(42);
a.join();
return 0;
}
問題
あなたはすでに気づいているかもしれませんが、ここでは微妙なバグがあります:Thread::ThreadStart(...)
Thread
CTORコンテキストから呼び出され、したがって、純粋の呼び出しは/仮想関数は派生クラスの実装を呼び出さない。これは、ランタイムエラーによって裏づけされています
pure virtual method called
terminate called without an active exception
Aborted
しかし私はThread
CTORにstd::cout
への呼び出しを削除すると、予期しない実行時の動作があります:
virtual void {anonymous}::A::Run(){anonymous}::Verbose::Verbose(int): : 042
virtual void {anonymous}::A::Run(): 1
virtual void {anonymous}::A::Run(): 2
virtual void {anonymous}::A::Run(): 3
virtual void {anonymous}::A::Run(): 4
すなわち、 Thread
ctorのstd::cout
への呼び出しを削除すると、派生クラス '基本クラス'コンストラクタのコンテキストから純粋/仮想関数を呼び出すことができるようになります。これは、事前の学習と経験に合致しません。 Windowsの10 gccのバージョンのCygwinのx64の中
ビルド環境は次のとおりです。私はこの観察によって困惑だし、何が起こっているかについての好奇心に燃えています
g++ (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
。誰でも光を流すことができますか?
何も予期しません。オブジェクトが特定の基底クラスAまでしか構築されていない場合、使用可能な仮想関数の実装はAから表示されるものだけです。 – EJP
それに加えてpost-ctorもありません。ここでとても役立つだろう... – Deduplicator