2016-06-27 9 views
1

で返します、私は値することにより、これらのいずれかを返すファクトリ関数を作成したので、動的メモリ割り当てを排除したいC++クラスの設計と私はこのようになりますクラス階層を持っている価値

class Address { 
public: 
    virtual ~Address() {} 

    enum Type { 
     Internal, External 
    }; 

    Type type() const { return _type; } 

protected: 
    Address(Type type) : _type(type) {} 

private: 
    Type _type; 
}; 

class InternalAddress : public Address { 
public: 
    InternalAddress(const string& portName) : Address(Internal), _portName(portName) {} 
    ~InternalAddress() {} 

    const string& portName() const { return _portName; } 
private: 
    string _portName; 
}; 

class ExternalAddress : public Address { 
public: 
    ExternalAddress(const string& handlerName) : Address(External), _handlerName(handlerName) {} 
    ~ExternalAddress() {} 

    const string& handlerName() const { return string("handler"); } 
private: 
    string _handlerName; 
}; 

に応じてパラメータ:

static Address addressForType(Address::Type type) { 
    if (Address::Internal == type) 
     return InternalAddress(); 
    else 
     return ExternalAddress(); 
} 

私は、このような何か:

int main(int argc, char **argv) { 
    Address address = addressForType(Address::External); 
    cout << ((ExternalAddress&)address).handlerName() << endl; 
} 

をanythがあります私がここでやっていることに間違っていますか?または、これはちょうど悪いデザインですか?私が尋ねる理由は、既存のシステムを変更しようとしているため、動的メモリ割り当てが少なくて済むからです。動的に割り当てられたオブジェクトではなく、値によって返されるコードを変更すると、 "handlerName()"メソッドによって返された文字列参照にアクセスしようとするとsegfaultが発生します。

これを行うより良い方法がある場合は、私に教えてください!私は、簡潔にするために、コピーコンストラクタと代入演算子を除外していることを付け加えます。これらのプレゼントがあっても、私は同じ結果を得ます。

ありがとうございました。

+2

デザインが不良です。あなたのコードは[オブジェクトのスライス](http://stackoverflow.com/questions/274626/what-is-object-slicing)に苦しんでいます。 –

+0

ありがとう!それはまさに私が探していたものです。再設計が進んでいます... – DaveR

+0

私は、主な設計上の問題は動的多型を使用するときに動的メモリを避けようとしていると思います。動的ツールは常に動的なリソースを何らかの方法で必要とします。静的ポリモーフィズムを使用するか、動的リソースの使用を避けることをあきらめてください。 – KABoissonneault

答えて

7

私はここで何をしていますか?

はい。あなたがやっていることはobject slicingと呼ばれ、あなたに望ましい動作を与えません。あなたが持っているのはAddressです。それはもはやInternalAddressまたはExternalAddressになりません。

これを行うより良い方法がある場合は、私に教えてください!

ある種の動的メモリ割り当てが必要になります。あなたの人生を楽にし、より安全にコードを作成するには、smart pointersを調べてください。メモリを管理してメモリリークを起こす可能性は非常に低くなります。

0

私はここで何をしていますか?または、これはちょうど悪いデザインですか?

あなたの機能addressForTypeには、object slicingがあります。

この

を行うには良い方法があればあなたはヒープメモリを使用して割り当てられたオブジェクトへのポインタを返し、呼び出し元の関数に返されたオブジェクトを削除することを確認する必要があります。

static Address* addressForType(Address::Type type) { 
    if (Address::Internal == type) 
     return new InternalAddress(); 
    else 
     return new ExternalAddress(); 
} 
1

あなたのファクトリ関数は、むしろstd::unique_ptr<Address>を返す必要があります:

static std::unique_ptr<Address> addressForType(Address::Type type) { 
    // ^^^^^^^^^^^^^^^^^^^^^^^^ 
    if (Address::Internal == type) 
     return std::make_unique<InternalAddress>(); 

    return std::make_unique<ExternalAddress>(); 
} 

other answerで述べたように、あなたがとにかくダイナミックな割り当てを避けることができません。


また工場が故にstd::unique_ptr、この場合のために正しい選択である、呼び出し側に所有権を提供する必要があります。

3

私はあなたがこれらのクラスにstd::stringオブジェクトを格納している、あなたはどちらか非常に努力して、または何動的メモリを誤解していないことを考えると

.....動的なメモリ割り当てを解消したいですC++で書かれています。

とにかく。

C++は継承(および一般的なオブジェクト)を「Javaであるが、いくつかの値のセマンティクスを持つ」ものとして扱っているように見えますが、これは間違っています。

次のコードは、ExternalAddressまたはInternalAddress多形アクセスを返さないように、それが構築しようとしたかもしれないもののサブクラスの少しツー知識なしで、リテラルAddressオブジェクトを返します。

static Address addressForType(Address::Type type) { 
    if (Address::Internal == type) 
     return InternalAddress(); 
    else 
     return ExternalAddress(); 
} 

結果として、これらの追加のオブジェクトに必要なタイプ情報と追加のスペースは、返されたオブジェクトから除外され、スライスされています(他のコメント/回答が示唆しているように)。

適切な多型が必要な場合は、ポインタ(std::shared_ptrおよびstd::unique_ptrが推奨されます)または参照によってオブジェクトを返す必要があります。

//replace with std::shared_ptr and std::make_shared<> if you're expecting the pointer to be "owned" by multiple handles, like is common in Java. 
static std::unique_ptr<Address> addressForType(Address::Type type) { 
    if (Address::Internal == type) 
     return std::make_unique<InternalAddress>(); 
    else 
     return std::make_unique<ExternalAddress>(); 
} 
+0

「else」は完全に余分です。 –

+2

@πάνταῥεῖ私は確信していません。論理的には、構文的には、yes:「else」はプログラムの機能を変更しません。それは意図をより明確にし、プログラムをより読みやすくします。 – Xirema

関連する問題