C ++ вводит условия в наследуемые классы - PullRequest
3 голосов
/ 14 апреля 2010

Я хотел бы определить абстрактный базовый класс X и применить следующее:

a) каждый конкретный класс Y, который наследуется от X, определяет конструктор Y (int x)

b) должна быть возможность проверить, равны ли два объекта Y.

Для одного, не очень хорошего решения - поместить чисто виртуальный метод fromInt в X какой конкретный класс придется определить. Но я не могу навязать строительство.

Для б) я не могу использовать чисто виртуальный метод в X

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

потому что в переопределенных классах это остается неопределенным. Недостаточно определить

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

потому что типы не совпадают. Как мне решить эти проблемы?

Ответы [ 6 ]

3 голосов
/ 14 апреля 2010

Вы можете принудительно создать конструкцию, сделав конструктор без аргументов закрытым и имея в своем базовом классе общедоступный конструктор с одним аргументом int. Пока базовый класс имеет несколько чисто виртуальных методов, ваши подклассы должны вызывать этот конструктор.

Что касается оператора ==, попробуйте определить

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

во всех ваших подклассах. В худшем случае вы можете определить публичный метод equals (const BaseClass и другие), который является чисто виртуальным в вашей базе.

РЕДАКТИРОВАТЬ: вещь принудительного конструктора не совсем верно. То, что я предложил, заставляет подклассы вызывать конструктор с одним аргументом. У них может быть конструктор без аргументов, который передает константу до базы в конструкторе.

2 голосов
/ 14 апреля 2010

Есть простое решение.

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

class X {
 ...
2 голосов
/ 14 апреля 2010

Для b) вы можете определить virtual bool operator == (const X & other) const = 0 в X.

Вы не можете иметь const Y & other в качестве параметра в сравнении, но Ys будет автоматически приведен к X, а затем вы можете использовать dynamic_cast, чтобы увидеть, можно ли сравнить этот класс с *.

0 голосов
/ 14 апреля 2010

Принудительное конструирование из целого числа не имеет никакого смысла: каждый производный класс может свободно определять своих конструкторов по своему усмотрению. Однако вы можете принудительно заставить их передавать целое число в базовый класс ... не то чтобы в любом случае это имело гораздо больший смысл.

operator== также искажен, однако вы можете получить суть этого:

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);
}

Вы можете попытаться немного улучшить его, используя шаблоны и CRTP, но что, если Derived был унаследован от? не выдержит.

0 голосов
/ 14 апреля 2010

а) не имеет смысла, как для меня, но вы можете создать что-то

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

для б) спросите Google о реализации "нескольких методов" в c ++

0 голосов
/ 14 апреля 2010

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;
  }
};

Очевидно, я многое оставил для вас, чтобы решить, как сделать это законченным решением.

...