我的问题是,我有一个派生类的基类。我在基类中有一个重载的+ =运算符,但我只希望能够添加相同类型的派生类。我这样做是通过返回lhs并在它们不是同一类型时产生警告消息。
class base{
int variable;
public:
base(int v);
base & operator+=(const base & rhs);
class a: public base{
}
class b: public base{
}
base & operator+=(const base & rhs){
if(type_same(const & rhs){
variable+=rhs.variable; }
return *this
}
a first(1);
a second(5);
b third(2);
first+=second // first.variable now =6
second+=third // warning produced second.variable still = 5
之前我从未使用过动态强制转换,所以我的问题是使用它和typeid进行检查是否可行/可取,以确定传递的类型是否相同。我的替代方案是每个派生类的字符串常量名称。
答案 0 :(得分:4)
为什么首先在基类中使用operator +?如果您只是将operator+
的正确类型放入a
和b
类,那么它就可以正常运行,而不会有dynamic_cast
。
dynamic_cast
通常暗示您的类型设计不合理,应避免使用。在所描述的场景中,您可以毫不费力地使用dynamic_cast
。如果不是,那么a
和b
不应该来自base
,因为它们的行为方式不同。从用户角度考虑:通过从a
派生base
,您告诉用户a
可以用作base
。如果方法需要实际类型,请将其向下移动而不是将其放入基本接口。
正确使用btw。将dynamic_cast
rhs改为当前类型(即dynamic_cast<b*>(&rhs)
)并且如果返回非零值,那么rhs
确实是正确的类型(但是,考虑一下如果有一个派生自b
的类,则会发生!)
答案 1 :(得分:2)
要解决您在帖子中说明的问题,dynamic_cast
和RTTI绝对是正确的工具。但是,在运行时发出警告,同时为'+'操作提供编译时支持可能会指向用户设计中的问题您的API不会完全期望您的API提供的行为。
答案 2 :(得分:1)
我的看法:您可以使用CRTP
以下代码将在编译时发出类型不匹配错误,如其他人所建议的那样。
template <typename Derived>
class base{
int variable;
public:
base(int v) { variable = v; }
Derived& operator+=(const Derived& rhs);
};
struct a: base<a> {
a(int v): base<a>(v) {}
};
struct b: base<b> {
b(int v): base<b>(v) {}
};
template <typename Derived>
Derived& base<Derived>::operator+=(const Derived& rhs)
{
variable += rhs.variable;
return static_cast<Derived&>(*this);
}
int main(int argc, const char *argv[])
{
a a1(1), a2(2);
b b1(1), b2(2);
a1 += a2;
b1 += a2; // compile time error :)
return 0;
}
即使您真的想要将运算符参数键入为base&
,您至少也可以获得使用static_cast<>
的好处,因为转换是精确的,并且在运行时定义良好。我可以在一些