Подтвердить что ты не робот

Как вызвать конструктор базового класса?

latley Я много программировал на Java. Там вы вызываете класс, который вы наследуете, с помощью super(); (все вы, вероятно, знаете это)

Теперь у меня есть класс в С++, который имеет конструктор по умолчанию, который принимает некоторые аргументы. Пример:

class BaseClass {
public:
    BaseClass(char *name); .... 

Если я наследую класс, он дает мне предупреждение, что нет подходящего конструктора по умолчанию. Итак, есть что-то вроде super() в С++, или мне нужно определить функцию, где я инициализирую все переменные?

4b9b3361

Ответ 1

Вы делаете это в списке инициализаторов конструктора подкласса.

class Foo : public BaseClass {
public:
    Foo() : BaseClass("asdf") {}
};

Конструкторы базового класса, которые принимают аргументы, должны быть вызваны там до инициализации любых элементов.

Ответ 2

В файле заголовка определите базовый класс:

class BaseClass {
public:
    BaseClass(params);
};

Затем определите производный класс как наследующий BaseClass:

class DerivedClass : public BaseClass {
public:
    DerivedClass(params);
};

В исходном файле определите конструктор BaseClass:

BaseClass::BaseClass(params)
{
     //Perform BaseClass initialization
}

По умолчанию производный конструктор вызывает только базовый конструктор по умолчанию без параметров; поэтому в этом примере конструктор базового класса НЕ вызывается автоматически, когда вызывается производный конструктор, но его можно достичь простым добавлением синтаксиса конструктора базового класса после двоеточия (:). Определите производный конструктор, который автоматически вызывает его базовый конструктор:

DerivedClass::DerivedClass(params) : BaseClass(params)
{
     //This occurs AFTER BaseClass(params) is called first and can
     //perform additional initialization for the derived class
}

Конструктор BaseClass вызывается перед конструктором DerivedClass, и те же/разные параметры params могут быть перенаправлены в базовый класс, если это необходимо. Это может быть вложено для более глубоких производных классов. Полученный конструктор должен вызывать ТОЧНО ОДИН базовый конструктор. Деструкторы AUTOMATICALLY вызываются в порядке REVERSE, который вызывались конструкторами.

EDIT: существует исключение из этого правила, если вы наследуете от любых классов virtual, как правило, для достижения множественного наследования или наследования алмазов. Затем вы ДОЛЖНЫ явным образом вызывать базовые конструкторы всех базовых классов virtual и явно передавать параметры, иначе они будут вызывать только их конструкторы по умолчанию без любых параметров. См. виртуальное наследование - пропуски конструкторов

Ответ 3

Вы должны использовать initiailzers:

class DerivedClass : public BaseClass
{
public:
  DerivedClass()
    : BaseClass(<insert arguments here>)
  {
  }
};

Это также то, как вы создаете членов своего класса, у которых нет конструкторов (или вы хотите их инициализировать). Любые члены, не упомянутые, будут инициализированы по умолчанию. Например:

class DerivedClass : public BaseClass
{
public:
  DerivedClass()
    : BaseClass(<insert arguments here>)
    , nc(<insert arguments here>)
    //di will be default initialized.
  {
  }

private:
  NeedsConstructor nc;
  CanBeDefaultInit di;
};

Порядок, в котором указаны члены, не имеет значения (хотя конструкторы должны быть первыми), но порядок, в котором они будут построены, находится в порядке объявления. Итак, nc всегда будет построено до di.

Ответ 4

Относительно альтернативы супер; вы в большинстве случаев используете базовый класс либо в списке инициализации производного класса, либо используя синтаксис Base::someData, когда вы выполняете работу в другом месте, а производный класс переопределяет данные.

struct Base
{
    Base(char* name) { }
    virtual ~Base();
    int d;
};

struct Derived : Base
{
    Derived() : Base("someString") { }
    int d;
    void foo() { d = Base::d; }
};

Ответ 5

Используйте имя базового класса в списке инициализаторов. Список инициализаторов появляется после сигнатуры конструктора перед телом метода и может использоваться для инициализации базовых классов и членов.

class Base
{
public:
  Base(char* name)
  {
     // ...
  }
};

class Derived : Base
{
public:
  Derived()
    : Base("hello")
  {
      // ...
  }
};

Или шаблон, используемый некоторыми людьми, - это определить "супер" или "базу" самостоятельно. Возможно, некоторые люди, которые предпочитают эту технику, - это разработчики Java, которые переходят на С++.

class Derived : Base
{
public:
  typedef Base super;
  Derived()
    : super("hello")
  {
      // ...
  }
};

Ответ 6

В С++ нет super(). Вы должны вызвать базовый конструктор явно по имени.