问题
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
andstatic_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