したがって、抽象メソッドのない抽象基本クラスがあります。抽象性を強制するために、(自明ではない) デストラクタを純粋な仮想として宣言しました。
class AbstractClass
{
public:
AbstractClass()
{
std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
}
virtual ~AbstractClass() = 0
{
std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
}
};
class ConcreteClass : public AbstractClass
{
public:
ConcreteClass()
{
std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
}
virtual ~ConcreteClass()
{
std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
}
};
これは期待どおりにビルドされ、機能します。ConcreteClass のインスタンスを単純に定義するコード ブロックの出力は次のとおりです。
抽象クラス::抽象クラス() コンクリートクラス::コンクリートクラス() ConcreteClass::~ConcreteClass() AbstractClass::~AbstractClass()
ここで、インターフェイス クラスとして使用される別のクラスから AbstractClass を派生させ、それ自体が (自明な) 仮想デストラクタ (純粋またはそれ以外) を持っている場合でも、それは機能します。
class IAlpha
{
public:
virtual ~IAlpha() = 0 {}
};
class AbstractClass : public IAlpha
{
public:
AbstractClass()
{
std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
}
virtual ~AbstractClass() = 0
{
std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
}
};
class ConcreteClass : public AbstractClass
{
public:
ConcreteClass()
{
std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
}
virtual ~ConcreteClass()
{
std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
}
};
この方法で 2 つの異なるインターフェイスを実装しようとすると、問題が発生します。
class IAlpha
{
public:
virtual ~IAlpha() = 0 {}
};
class IBeta
{
public:
virtual ~IBeta() = 0 {}
};
class AbstractClass : public IAlpha, public IBeta
{
public:
AbstractClass()
{
std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
}
virtual ~AbstractClass() = 0
{
std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
}
};
class ConcreteClass : public AbstractClass
{
public:
ConcreteClass()
{
std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
}
virtual ~ConcreteClass()
{
std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
}
};
この時点で、ビルド時に次の警告が表示されます。
警告 C4505: 'AbstractClass::~AbstractClass': 参照されていないローカル関数が削除されました
しかし、奇妙なことに、出力はまだAbstractClass::~AbstractClass()
呼び出されていることを示しています。
これは MSVC9 (VS 2008) のバグですか? この警告を無視しても問題ありませんか?
= 0 {}
編集:明らかに構文が実際には有効ではないため、純粋仮想メソッド定義をクラス定義から分離しようとしました。残念ながら、指定するかどうかに関係なく、C4505 は引き続き表示されますinline
。
これらのメソッドに対してのみこの警告を出す方法が見つからないため#pragma
(警告はコードの他の部分からトリガーされます)、純粋な仮想指定子を削除AbstractClass
して、コンストラクターを保護することに依存する必要がある場合があります。理想的な解決策ではありませんが、誤った警告を回避するためにクラス階層を再設計するよりはましです。