我想对以下类实现“less”类型的操作:
class Base {
public:
virtual int type() const = 0;
private:
int b;
};
class Derived1 : public Base{
public:
virtual int type() const { return 1; }
private:
int d1;
};
class Derived2 : public Base{
public:
virtual int type() const { return 2; }
private:
int d2;
};
where
o1 < o2
如果它的类型更小,如果类型相等则比较元素(首先是 b 然后是 d1 或 d2)。
请注意,还有其他具有类似问题结构的操作(例如等于)。
如何在不使用
dynamic_cast
的情况下做到这一点?
你不需要
dynamic_cast
也不需要type
。就此而言,也根本没有公共成员。
class Base {
virtual bool less( Base const & rhs ) const {
return false;
}
int b;
friend bool operator < ( Base const & lhs, Base const & rhs ) {
std::type_info const & ltype = typeid (lhs);
std::type_info const & rtype = typeid (rhs);
if ( ltype == rtype ) {
if ( lhs.b < rhs.b ) return true;
if ( rhs.b < lhs.b ) return false;
return lhs.less( rhs ); // Dynamic types of lhs and rhs already match.
}
return ltype.before( rtype );
}
};
class Derived1 : public Base{
virtual bool less( Base const & rhs_base ) const {
// Since rhs_base is known to be of this type, use static_cast.
Derived1 const & rhs = static_cast< Derived1 const & >( rhs_base );
return d1 < rhs.d1;
}
int d1;
};
// Same for Derived2
经营者可以看下面的方式
class Base {
public:
virtual int type() const = 0;
virtual int get_value() const { return b; }
private:
int b;
};
class Derived1 : public Base{
public:
virtual int type() const { return 1; }
virtual int get_value() const { return d1; }
private:
int d1;
};
class Derived2 : public Base{
public:
virtual int type() const { return 2; }
virtual int get_value() const { return d2; }
private:
int d2;
};
bool operator <( const Base &lhs, const Base &rhs )
{
int t1 = lhs.type();
int t2 = rhs.type();
int b1 = lhs.Base::get_value();
int b2 = rhs.Base::get_value();
int d1 = lhs.get_value();
int d2 = rhs.get_value();
return std::tie( t1, b1, d1 ) < std::tie( t2, b2, d2 );
}
这是一个演示程序。我又添加了一个派生类,以表明运算符不依赖于派生类的数量。
#include <iostream>
#include <iomanip>
#include <tuple>
class Base
{
public:
Base( int x ) : b( x ) {}
virtual int type() const = 0;
virtual int get_value() const { return b; }
private:
int b;
};
class Derived1 : public Base
{
public:
Derived1( int x, int y ) : Base( y ), d1( x ) {}
virtual int type() const { return 1; }
virtual int get_value() const { return d1; }
private:
int d1;
};
class Derived2 : public Base
{
public:
Derived2( int x, int y ) : Base( y ), d2( x ) {}
virtual int type() const { return 2; }
virtual int get_value() const { return d2; }
private:
int d2;
};
class Derived3 : public Base
{
public:
Derived3( int x, int y ) : Base( y ), d3( x ) {}
virtual int type() const { return 2; }
virtual int get_value() const { return d3; }
private:
int d3;
};
bool operator <( const Base &lhs, const Base &rhs )
{
int t1 = lhs.type();
int t2 = rhs.type();
int b1 = lhs.Base::get_value();
int b2 = rhs.Base::get_value();
int d1 = lhs.get_value();
int d2 = rhs.get_value();
return std::tie( t1, b1, d1 ) < std::tie( t2, b2, d2 );
}
int main()
{
Derived1 d11( 1, 2 );
Derived1 d12( 1, 1 );
std::cout << "d11 < d12 = " << std::boolalpha <<( d11 < d12 ) << std::endl;
std::cout << "d12 < d11 = " << std::boolalpha <<( d12 < d11 ) << std::endl;
Derived2 d21( 1, 2 );
std::cout << "d21 < d11 = " << std::boolalpha <<( d21 < d11 ) << std::endl;
std::cout << "d11 < d21 = " << std::boolalpha <<( d11 < d21 ) << std::endl;
Derived3 d31( 1, 2 );
std::cout << "d31 < d21 = " << std::boolalpha <<( d31 < d21 ) << std::endl;
std::cout << "d21 < d31 = " << std::boolalpha <<( d21 < d31 ) << std::endl;
}
程序输出为
d11 < d12 = false
d12 < d11 = true
d21 < d11 = false
d11 < d21 = true
d31 < d21 = false
d21 < d31 = false
你需要双重派遣:
class Base
{
public:
virtual int type() const = 0;
virtual bool greaterWithBase(const Base&) const = 0;
virtual bool lessWithDerived1(const Derived1&) const = 0;
virtual bool lessWithDerived2(const Derived2&) const = 0;
private:
int b;
};
class Derived1 : public Base
{
public:
int type() const override { return 1; }
bool greaterWithBase(const Base& base) const override
{
return base.lessWithDerived1(*this);
}
bool lessWithDerived1(const Derived1& rhs) const override
{
return std::tie(b, d1) < std::tie(rhs.b, rhs.d1);
}
bool lessWithDerived2(const Derived2&) const override {return true;}
private:
int d1;
};
class Derived2 : public Base
{
public:
int type() const override { return 1; }
bool greaterWithBase(const Base& base) const override
{
return base.lessWithDerived2(*this);
}
bool lessWithDerived1(const Derived1&) const override {return false;}
bool lessWithDerived2(const Derived2& rhs) const override
{
return std::tie(b, d2) < std::tie(rhs.b, rhs.d2);
}
private:
int d2;
};