このようにすることもできます。それはホルトの答えほど専門的ではありませんが、同じ欠点を共有しています。後で詳しく説明します。
#include <iostream>
#include <memory>
struct Base {
virtual int what() const = 0;
virtual ~Base(){}
};
struct Derived1 : Base {
static constexpr int ME = 1;
int what() const{
return ME;
}
};
struct Derived2 : Base {
static constexpr int ME = 2;
int what() const{
return ME;
}
};
using pBase = std::unique_ptr<Base>;
void doSomething(pBase &base){
switch(base->what()){
case Derived1::ME :
std::cout << "Derived1" << std::endl;
break;
case Derived2::ME :
std::cout << "Derived2" << std::endl;
break;
default:
std::cout << "huh?" << std::endl;
}
}
int main(){
pBase base1{ new Derived1() };
pBase base2{ new Derived2() };
doSomething(base1);
doSomething(base2);
//no need to call delete
}
私はsmart pointer
とC++11
を使用してコードをしました。もしあなたがC++11
と一緒に働いていなかったら、それをチェックしてください、あなたはそれを愛するでしょう。
なぜこのコードはHoltのコードより専門性が低いのですか?
タイプとキャストの代わりに、具体的にタイプを識別するために作られた単純なint
値に依存するためです。
は、しかし、私の意見では、主な質問はかなり異なっている:
両方のコードの欠点は何ですか?
両方のコードでは、クライアントはすべての派生クラスを認識している必要があります。ホルトの答えでは、これはif statements
の部分です。私の答えでは、これはswitch statement
です。
新しい派生クラスDerived3があるとどうなりますか?クライアントコードを変更する必要があります。
多形性でこれを行うことができ、キャストなしでBase
クラスでのみ動作すると思います。数字、人(学生、教授)、車(スポーツ、ピックアップ、SUVの、トラック) -
例
はこのような例がたくさんあります。
#include <iostream>
#include <memory>
struct Shape {
virtual float area() const = 0;
virtual const char *name() const = 0;
virtual ~Shape(){}
};
struct Square : Shape {
Square(float a) : a(a){
}
const char *name() const override{
return "Quadrat"; // this has nothing to do with class name
}
float area() const override{
return a * a;
}
private:
float a;
};
struct Circle : Shape {
Circle(float r) : r(r){
}
const char *name() const override{
return "Circle";
}
float area() const override{
return PI * r * r;
}
private:
constexpr static float PI = 3.14159;
float r;
};
using pShape = std::unique_ptr<Shape>;
void doSomething(pShape &base){
std::cout << base->name()
<< " has area of "
<< base->area()
<< "m2"
<< std::endl;
}
int main(){
pShape base1{ new Square(5) };
pShape base2{ new Circle(5) };
doSomething(base1);
doSomething(base2);
//no need to call delete
}
ベースShape
クラスはinterface
と呼ばれJava
、C#
またはPHP
、など多くのOOP言語で:これは私のお気に入りであることを起こります。どのようにメソッドを定義するかに注目してください。実装の詳細は含まれていません。
これにより、派生クラスを異なるコンパイル単位で実装することができ、クライアントコードはどのクラスで動作するか分かりません。あなたの例の場合も同様である
(typeid(*baseComp) == typeid(ComponentB))
:
こんにちは、私はいくつかの時間に同じ問題を抱えていました。しかし、あなたが言ったように、私はいつもBaseComponentに "type"を追加して列挙し、subClass(またはsubStruct)を構築する際に特定の型に初期化することになりました...動的に型を取得することはできません – Stefano
ええ、それは私のバックアップ計画ですしかし、別の方法がある場合、IDは知っているが、あなたのコメントのためにとにかくあなたのコメントのためにたくさんありがとう:) –
javaで参照親クラスが派生クラスのインスタンスであるかどうかを確認することができます。 –