コンストラクタを明示的にすると、派生クラスによって暗黙的に呼び出されるのを防ぐことができないのはなぜですか?
class A{
public:
explicit A(){}
};
class B : public A{
public:
B(){ //Constructor A() is called implicitly
//...
}
}
むしろ、プログラムの中で状況があったその場合にコンパイラエラーが発生すると、バグを見つけるための時間を大幅に節約できます。今のところ、それを実現するためにダミーの「int」引数を受け入れるようにAのデフォルトコンストラクタを変更しましたが、これに対して「明示的」なキーワードは機能しませんか?
g ++-4.8は、エラーや警告なしで上記のコードをコンパイルします。
回答:
回答№1は8あなたの仮定は間違っています explicit
キーワード。
ザ explicit
キーワード コンストラクターが派生クラスから呼び出されないようにすることを意図していない むしろ 暗黙的な変換を防ぐため こちらのサンプルのように: https://stackoverflow.com/a/121163/1938163
ここで関連する部分を要約します。
class Foo
{
public:
// single parameter constructor, can be used as an implicit conversion
Foo (int foo) : m_foo (foo)
{
}
int GetFoo () { return m_foo; }
private:
int m_foo;
};
あいまいさを解決するために最大で1つの暗黙的な変換を実行できるため、次のような関数がある場合
void DoBar (Foo foo)
{
int i = foo.GetFoo();
}
以下は合法です:
int main ()
{
DoBar (42); // Implicit conversion
}
そして、それはまさに、明示的なキーワードが作用する場所です。上記のケースを禁止します。
問題を解決するには、クラスが基本クラスとして使用されるのを防ぐために、コンストラクターに 最後の C ++ 11を使用している場合(http://en.wikipedia.org/wiki/C++11#Explicit_overrides_and_final)
回答№2の場合は1
明白な キーワードは通常、1つのパラメーターを持つコンストラクターで使用されます。パラメータの型からクラスの型へのオブジェクトの暗黙的な構築を防ぎます。
以下の例はコンパイルされますが、通常は望みのものではありません。
#include <iostream>
using namespace std;
struct Test
{
Test(int t) {}
};
void test_fun(Test t) {}
int main() {
test_fun(1); //implicit conversion
return 0;
}
と 明白な この例のキーワードはコンパイルできません:
#include <iostream>
using namespace std;
struct Test
{
explicit Test(int t) {}
};
void test_fun(Test t) {}
int main() {
test_fun(1); //no implicit conversion, compiler error
return 0;
}