Не понял следующий комментарий (выделен жирным шрифтом) к Брюсу Эккелю "Мышление в C ++" на его странице 624 Vol. 1 - PullRequest
0 голосов
/ 22 января 2012
#include <fstream>
using namespace std;
ofstream out("order.out");

#define CLASS(ID) class ID { \
public: \
  ID(int) { out << #ID " constructor\n"; } \
  ~ID() { out << #ID " destructor\n"; } \
};

CLASS(Base1);
CLASS(Member1);
CLASS(Member2);
CLASS(Member3);
CLASS(Member4);

class Derived1 : public Base1 {
  Member1 m1;
  Member2 m2;
public:
  Derived1(int) : m2(1), m1(2), Base1(3) {
    out << "Derived1 constructor\n";
  }
  ~Derived1() {
    out << "Derived1 destructor\n";
  }
};

class Derived2 : public Derived1 {
  Member3 m3;
  Member4 m4;
public:
  Derived2() : m3(1), Derived1(2), m4(3) {
    out << "Derived2 constructor\n";
  }
  ~Derived2() {
    out << "Derived2 destructor\n";
  }
};

int main() {
  Derived2 d2;
}

"Обратите внимание, что конструкторы не являются конструкторами по умолчанию; у каждого из них есть аргумент int. Сам аргумент не имеет идентификатора; единственная причина его существования - заставить вас явно вызывать конструкторы в инициализаторесписок"

Ответы [ 3 ]

1 голос
/ 22 января 2012

Поскольку классы имеют определяемый пользователем конструктор и этот определяемый пользователем Конструктор не является конструктором по умолчанию, по умолчанию Конструктор доступен в этих классах.

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

class Derived : public Base {
  Derived() {} // fails to compile, no constructor Base::Base() available
  Derived() : Base(3) {} // works
};

Так много за то, что делает код и как он этого добивается. Я понятия не имею почему вам когда-нибудь нужно что-то подобное, но вы никогда не знаете.

0 голосов
/ 22 января 2012

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

Чтобы упростить этот демонстрационный код:

#include <iostream>

struct ID
{
    ID(int)
    {
        std::cout << "ID  constructor" << std::endl;
    }
};

int main()
{
    ID this_will_compile(0);
    ID this_will_not_compile;
}

Хотя первое создание экземпляра ID будет успешным, вторая попытка не удастся,Ваш компилятор скажет вам что-то вроде:

ошибка: нет соответствующей функции для вызова 'ID :: ID ()'

То же самое относится и к получению из такихкласс:

Это будет работать ...

struct DerivedWorking: public ID
{
    DerivedWorking()
        :ID(0)
    {
    }
};

В то время как это не будет, потому что он не предоставляет конструктор int для ID ...

struct DerivedBroken: public ID
{
    DerivedBroken()
    {
    }
};
0 голосов
/ 22 января 2012

Что означает, что у аргумента нет идентификатора - нет имени - и, следовательно, он не используется нигде в конструкторе.

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

Если бы у родительского класса был конструктор по умолчанию (без аргументов), вам не пришлось бы его вообще вызывать - это было бы сделано автоматически. Также, если вы не инициализируете член объекта, это будет сделано автоматически через конструктор по умолчанию.

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

Использование безымянного аргумента во всех классах делает именно это - заставляет вас явно вызывать их конструкторы, а не просто полагаться на вызываемый конструктор по умолчанию.

...