我的类结构如下:
class P {
public:
virtual std::auto_ptr<P> clone() const=0;
};
class A : public P {
public:
std::auto_ptr<P> clone() const {
return std::auto_ptr<P>(new A(*this));
}
};
class B : public P {
public:
std::auto_ptr<P> clone() const {
return std::auto_ptr<P>(new B(*this));
}
};
class C : public P {
public:
std::auto_ptr<P> clone() const {
return std::auto_ptr<P>(new C(*this));
}
};
这只是复制构造函数的代码:类A
,B
,C
的代码全部不同。这里有很多代码重复,可以简化吗?
答案 0 :(得分:1)
使用CRTP,您可以这样做:
library(purrr)
out <- map2_dfr(lst1, lst2, ~ map2_dfr(.x, map(.y, "date"),
~ cbind(.x, date = .y), .id = 'IDGroup2'), .id = 'IDGroup')
head(out)
# IDGroup IDGroup2 holiday temp wind humidity barometer weekday weekend workday_on_holiday weekend_on_holiday
#1 5 2016-01-01 -0.2875051 -0.004131595 -0.68942320 0.08788958 -0.044270176 0.08152994 0 -0.004491160 0
#2 5 2016-01-01 -0.2613214 0.075470507 0.15884757 0.11554980 -0.027390966 0.11183146 0 -0.004928516 0
#3 5 2016-01-01 -0.2788497 0.148605376 0.84752327 0.08082478 -0.110819362 0.07685963 0 -0.009905681 0
#4 5 2016-01-01 -0.2852835 -0.011284750 0.11122661 0.13438693 -0.013517623 0.09257593 0 -0.005359963 0
#5 5 2016-01-01 -0.2827380 0.012600235 -0.08916214 0.16819011 0.017435972 0.07898130 0 -0.005911979 0
#6 5 2016-01-01 -0.2799886 0.055347286 -0.29320240 0.07062373 -0.009474599 0.08682005 0 -0.004491160 0
# protocol_active text_fog text_light_rain text_mostly_cloudy text_passing_clouds text_rain text_scattered_clouds text_sunny month_1
#1 0 0.05453610 0.02055504 -0.003508107 0.011477915 0.0248998813 -0.08106078 0.0086088600 0.07640738
#2 0 0.07014788 0.03472626 -0.010609524 0.014214168 -0.0004061495 -0.07777867 0.0031850194 0.16343993
#3 0 0.02396879 0.03373001 -0.008926486 0.008658116 -0.0329548903 -0.17243122 0.0063267332 0.08468129
#4 0 0.06937934 0.02769369 0.007768817 0.023657059 -0.0005894799 -0.08510636 0.0009107648 0.15761615
#5 0 0.07031541 0.02747060 -0.024575127 0.014786102 0.0011341455 -0.07967515 0.0057251817 0.07625937
#6 0 0.04563824 0.02055504 -0.014174540 0.014693571 -0.0004061495 -0.09679305 0.0106474124 0.08535635
# month_2 month_3 month_4 month_5 month_6 month_7 month_8 month_9 month_10 month_11 month_12 date
#1 0.045578238 0.0033622182 -0.06274214 -0.07467288 -0.032955777 -0.01001179 -0.03556978 0.01872355 0.07136117 0.05808590 0.15059333 2010-01-01
#2 0.018249372 0.0044576218 -0.17375310 -0.14704236 -0.007879189 -0.01295435 -0.04510764 0.01888210 0.07714521 0.08734045 0.25044793 2010-01-02
#3 0.002464291 -0.0292761438 -0.08312281 -0.08700808 -0.007707109 -0.01470387 -0.04435510 0.01596025 0.05754736 0.05717132 0.08667592 2010-01-03
#4 0.039944258 -0.0004514736 -0.15914200 -0.15421098 -0.008650888 -0.01224635 -0.04510764 0.01888210 0.07671589 0.08638439 0.17999160 2010-01-04
#5 0.047762766 0.0162581336 -0.14487271 -0.08386189 -0.008392147 -0.01224635 -0.04510764 0.01905395 0.07042630 0.11087914 0.11585888 2010-01-05
#6 0.022514986 0.0057770289 -0.13264991 -0.10598666 -0.037495021 -0.01280877 -0.03657964 0.01905395 0.07222101 0.08583542 0.17929509 2010-01-06
为了使派生类的实类型受益,我将代码修改为:
template <typename Derived, typename Base>
struct Clonable : public Base
{
std::auto_ptr<Base> clone() const {
return std::auto_ptr<Base>(new Derived(static_cast<const Derived&>(*this)));
}
};
class A : public Clonable<A, P> {};
class B : public Clonable<B, P> {};
class C : public Clonable<C, P> {};
因此,以下内容有效:
class P {
public:
std::auto_ptr<P> clone() const { return std::auto_ptr<P>(vclone()); }
private:
virtual P* vclone() const = 0;
};
template <typename Derived, typename Base>
struct Clonable : public Base
{
std::unique_ptr<Derived> clone() const {
return std::unique_ptr<Derived>(static_cast<Derived*>(vclone()));
}
private:
// Cannot use covariant-type `Derived*` in CRTP as Derived is not complete yet
Base* vclone() const {
return new Derived(static_cast<const Derived&>(*this));
}
};
class A : public Clonable<A, P> {};
class B : public Clonable<B, P> {};
class C : public Clonable<C, P> {};
答案 1 :(得分:0)
可以在基类中定义副本构造函数并且仍然处理派生类情况吗?
通常,简短的回答是“否”。
如果编译器生成的副本构造函数足够,则可以正常工作。
如果定义了一个派生类,使得编译器生成的副本构造函数不足,则无法解决在派生类中定义一个的需求。
答案 2 :(得分:0)
如果您的意思是说是否有一种方法可以给每个派生类一个克隆方法,而不必显式地写出来:答案是否定的。如果将元类添加到C ++中,这将成为可能,但不要指望在一段时间内使其成为语言。
但是,Boost.Any可以在不知道其动态类型的情况下复制对象,并且可以在C ++ 03中实现。如果愿意,可以使用类似的类型擦除技术。简而言之,它将包括:
ClonablePBase
方法和虚拟析构函数的clone
类ClonableP
派生的ClonablePBase
类模板。类型为ClonableP<T>
的对象(其中T
是从P
派生的)持有一个T
对象,并且知道如何使用T
的副本构造函数对其自身进行克隆。 AnyP
的{{1}}类。它通过调用虚拟克隆方法来复制自身。