Создание подкласса и использование инициализатора базового класса

#c #class #derived-class

#c #класс #производный класс

Вопрос:

У меня есть это:

 class foo {
public:
  int a;
  int b;
  int c;
};
  

Это нормально, но я хочу добавить некоторую перегрузку оператора без изменения класса foo:

 class bar: public foo {
  operator==(const bar amp;x) const {
    return a == x.a;
  }
}
  

Пока все в порядке, но теперь мне нужно инициализировать bar массивом объектов, которые я получаю из другого класса. Нет проблем, я могу просто скопировать все переменные foo в bar в специальном конструкторе:

 bar::bar(foo amp;x) {
  a = foo.a;
  /* etc */
}
  

Но это кажется запутанным, и если класс foo over обновляется, тогда мне тоже нужно обновить bar. Гораздо предпочтительнее, если бы bar мог автоматически инициализировать себя (он никогда не будет содержать свои собственные элементы данных)

Ответ №1:

разве это не так просто, как убедиться, что у Foo есть конструктор копирования…….

 bar::bar(foo amp;x) 
: foo(x)
{
}

class foo {
foo::foo(foo amp;x)
{
  a = foo.a; /* etc */
}

};
  

Комментарии:

1. foo как указано в вопросе, уже имеет конструктор копирования по умолчанию. Вам не нужно ничего добавлять, просто вызовите это.

2. Я прочитал это снова, и я не вижу, где говорится, что у Foo уже есть конструктор копирования. У меня создалось впечатление, что он напечатал все соответствующее определение класса для Foo в своем примере.

3. Если класс выглядит так, как в вопросе, компилятор сгенерирует для него конструктор копирования по умолчанию, выполняя копирование всех элементов по элементам.

Ответ №2:

Ну, просто:

 bar::bar(const fooamp; x)
  : foo(x)
{
}
  

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

 foo::foo(const fooamp; other)
  : a(other.a)
  , b(other.b)
  , c(other.c)
{
}
  

Обратите внимание, что я принимаю оба аргумента по ссылке const, что является хорошей практикой, поскольку вы не касаетесь других объектов. Также обратите внимание, что в большинстве случаев нет необходимости писать конструктор копирования для foo себя, только когда ваш класс содержит необработанные указатели ( int* например). Компилятор сам сгенерирует ctor для копирования, если вы его не определите, а просто создадите поверхностную копию всех элементов данных.

Ответ №3:

Наследование конструкторов невозможно выполнить в C 03, но может быть приближено. Добавьте эти конструкторы:

 template<class T1> bar(const T1amp; x1) : foo(x1) {}
template<class T1, class T2> bar(const T1amp; x1, const T2amp; x2) : foo(x1, x2) {}
template<class T1, class T2, class T3> bar(const T1amp; x1, const T2amp; x2, const T3amp; x3) : foo(x1, x2, x3) {}
// as much as you need...
  

В C 0x используется конструктор с одним шаблоном и совершенной пересылкой.

Комментарии:

1. Да ? Если вы просто хотите, чтобы производный класс можно было инициализировать из базового класса, это, несомненно, возможно в C 03.

2. @Xeo: копирование инициализировано — возможно. Наследовать конструкторы — невозможно. Просто попробуйте расширить vector с помощью нового метода и посмотрите, в чем проблемы…

3. В любом случае, по-видимому, это не совсем то, чего хотела операционная система… (хотя это тоже решает его / ее проблему).