3

我想定义一个抽象基类 X 并执行以下操作:

a) 每个从 X 继承的具体类 Y 定义一个构造函数 Y(int x)

b) 应该可以测试两个 Y 对象是否相等。

对于一个,一个不太好的解决方案是在 X 中放置一个纯虚拟 fromInt 方法,具体类必须定义该方法。但我不能强制施工。

对于 b),我似乎无法在 X 中使用纯虚方法

bool operator == (const X& other) const =0;

因为在重写的类中,这仍然是未定义的。定义是不够的

bool operator == (const Y& other) const { //stuff}

因为类型不匹配。我该如何解决这些问题?

4

6 回答 6

3

您可以通过将无参数构造函数设为私有并在基类中使用公共单 int 参数构造函数来强制构造。只要基类有一些纯虚方法,那么你的子类就必须调用那个构造函数。

至于运算符==,请尝试

bool operator == (const BaseClass& other) const { .. };

在所有子类中进行定义。最坏的情况是,您可以在您的基础中定义一个纯虚拟的公共 equals(const BaseClass& other) 方法。

编辑:强制构造函数的事情并不完全正确。我的建议强制子类调用单参数构造函数。他们可以有一个无参数构造函数,将一个常量传递给构造函数中的基类。

于 2010-04-13T21:37:18.593 回答
2

对于 b),您可以virtual bool operator == (const X & other) const = 0在 X中定义。

比较时不能const Y & other作为参数,但是 Ys 会自动转换为 Xs 然后你可以使用 dynamic_cast 来查看它是否是你可以比较的类。

于 2010-04-13T21:44:35.190 回答
2

有一个简单的解决方案。

// Class X
// (... some documentation ...)
//
// ** NOTE: All subclasses of X must have a constructor that takes a single int,
// ** and overload operator==.

class X {
 ...
于 2010-04-13T21:49:11.393 回答
0

a - 如果您使用 CRTP 和所有用户代码必须继承的中介、朋友、模板化子类,则应该是可能的。像这样:


struct X 
{
  virtual bool compare(X const&) const = 0;
private:
  X();

  template < typename T >
  friend struct client_base; // don't recall the correct code here.
};


template < typename Sub >
struct client_base : X
{
  // use boost::concepts to verify Sub has Sub(int)
  Sub() : X() {}
};

struct Y : client_base<Y>
{
  Y(int);

  bool compare(X const& x)
  {
    if ((Y* other = dynamic_cast<Y*>(x)) && *other == *this) return true;
    return false;
  }
};

显然,我为您留下了很多东西来解决这个问题。

于 2010-04-13T21:39:11.723 回答
0

a) 对我没有感觉,但你可以创造一些东西

template< typename T >
Base* create( int x )
{
    return T::create( x );
}

对于 b) 向谷歌询问 C++ 中的“多方法”实现

于 2010-04-13T21:40:58.230 回答
0

Enforcing to be constructible from an integer does not make any sense: each derived class is free to define its constructors as it wishes. You can however enforce them to pass an integer to the base class... not that it makes much more sense anyway.

The operator== is also contorted, you can however get the essence of it:

class Base
{
public:
  bool operator==(const Base& rhs) const;
  bool operator!=(const Base& rhs) const { return !(*this == rhs); }

private:
  virtual bool equals(const Base& rhs) const = 0; // will pass only objects
                                                  // of the same dynamic type
};

bool Base::operator==(const Base& rhs) const
{
  return typeid(*this) == typeid(rhs) && this->equals(rhs);
}

bool Derived::equals(const Base& rhs) const // We KNOW Base is actually a Derived
{
  return *this == static_cast<const Derived&>(rhs);
}

You could try and prettify it a bit by using templates and CRTP, but what if Derived was inherited from ? it would not hold.

于 2010-04-14T09:15:29.547 回答