Polymorphism with copy constructor

冷暖自知 提交于 2020-01-04 15:17:28

问题


Here is the code I use. I'd like to know if what I did is correct and safe. Normally it compiles and the tests I did are successful. But as it is the first time that I use dynamic_cast and static_cast, I'd like to be sure that I didn't miss anything.

Can you please check :

  • that I don't forget to delete any pointer (I don't really understand what my clone method does...)
  • if I use correctly dynamic_cast and static_cast
  • that there is not a more efficient of doing it

But my main concern is that I correctly implement the clone() method

Thanks a lot!!!

Edit

Thanks to some answer I realized that I should redesign my code. So I could get rid of this piece of code...

the .hpp file:

#include <vector>

/*!Base class that will never be instantiate. It provides a way to create
 * GenericData with defferent type. */
class Data{
    public:
        /*!Constructor*/
        Data(std::string name):name_(name){}
        /*!Destructor, must be virtual*/
        virtual ~Data(){};

        /*!Method that allows a copy of the derived class*/
        virtual Data* clone() const = 0;

    protected:
        std::string name_;//!< Name of the (Generic)Data 

};

/*!Derived class that can contain any one value of any type and of name name_*/
template<typename Type>
class GenericData : public Data{
    public:
        /*!Constructor*/
        GenericData(std::string name, Type t): Data(name), t_(t){}
        /*!Destructor*/
        ~GenericData(){};

        /*!Method that implements*/
        GenericData<Type>* clone() const { return new GenericData<Type>(static_cast<GenericData<Type> const&>(*this) );}

        /*!Returns the value of the data*/
        Type const& get_val() const {return t_;}

    private:
        Type t_;//!< Value of the GenericData
};

/*!Contains a vector of Data*, can store diffrent GenericData*/
class Container{
    public:
        Container(){};
        Container(Container const& c){ 
            for(unsigned int i(0);i<c.data_.size();i++){
                data_.push_back((c.data_[i])->clone());
            }
        }
        ~Container(){
            for(unsigned int i(0);i<data_.size();i++){
                delete data_[i];
                data_[i] = NULL;
            }
        }

        /*!Add one GenericData<Type> of value t and named name*/
        template<typename Type>
            void set(std::string name, Type const& t){data_.push_back(new GenericData<Type>(name,t));}

        /*!Returns the value GenericData<Type>::t_ named name*/
        template<typename Type>
            Type get(std::string name) const;

    private:
        std::vector<Data*> data_;
};

template<typename Type>
void Container::set(std::string name, Type const& t){
    data_.push_back(new GenericData<Type>(name,t));
}

template<typename Type>
Type Container::get(std::string name) const {
    for(unsigned int i(0);i<data_.size();i++){
        if(data_[i]->get_name()==name){
            return dynamic_cast< GenericData<Type> *>(data_[i])->get_val();
        }
    }
    std::cerr<<"Container : get(string name) : no data with name "<<name<<std::endl;
    return 0;
}

回答1:


GenericData<Type>* clone() const{
    return new GenericData<Type>(static_cast<GenericData<Type> const&>(*this) );
}

Here you don't need to use static_cast because type of *this is already const GenericData<Type>&.

================================================

    if(data_[i]->get_name()==name){
        return dynamic_cast< GenericData<Type> *>(data_[i])->get_val();
    }  

Here you need to check whether dynamic_cast returns null pointer. null pointer will be returned if data_[i] is not of type GenericData<Type>* (or if it's not a pointer to some type derived from GenericData<Type>)

=============================================
You also need to define Container::operator=. If you don't define it the compiler will generate it for you and vector<Data*> can be improperly copied.

=============================================

Also my advice is to use std::shared_ptr<Data> (of boost::shared_ptr<Data> if you use C++98) or std::unique_ptr<> instead of Data* to avoid manual object deletion and related potential memory leaks.




回答2:


Disregarding that you are re-implementing std::map in a terrible way (do you really want to allow storing GenericData<string> and GenericData<float> in the same container?), your clone method should not even compile because you are invoking GenericData<T>'s copy constructor without having defined one. How about this simple and readable alternative:

Data* clone() const {
    return new GenericData<Type>(name_, t_);
}


来源:https://stackoverflow.com/questions/22008053/polymorphism-with-copy-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!