Почему в C ++ отсутствует ключевое слово "initialization", как в Delphi? - PullRequest
3 голосов
/ 09 декабря 2010

Перед переключением на C ++ мы обнаружили, что языковой элемент initialization в Delphi чрезвычайно полезен. Это позволило вам иметь код в каждом модуле, который будет вызываться при запуске программы, чтобы вы могли инициализировать различные элементы этого модуля.

По нашему мнению, это облегчает работу и помогает поддерживать чистоту кода.

  • Так почему же нет initialization и finalization в C ++?

  • Каковы наши варианты замены этой языковой функции в C ++?

Ответы [ 8 ]

7 голосов
/ 09 декабря 2010

Эквивалентная особенность C ++ - конструкторы и деструкторы для объектов области видимости / глобальных объектов. Например:

#include <iostream>
using std::cout;

struct X {
   X() { cout << "X::X()\n"; }
   ~X() { cout << "X::~X()\n"; }
};

static X x;

int main() { cout << "main()\n"; return 0; }

выдаст

X::X()
main()
X::~X()

при запуске.

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

3 голосов
/ 10 декабря 2010

Вопрос 1: почему нет ключевого слова?

Никто, кроме Страуструпа или членов комитета, не может по-настоящему ответить, почему C ++ такой, какой он есть, но мы можем предположить, что, возможно, он не считался достаточно важным для ключевого слова. Стандарт C ++ говорит о порядке инициализации, например, для объектов, но порядок не является строго определенным и оставлен для реализации. Вот одна цитата (3.6.2 / 3):

Это определяется реализацией или нет динамическая инициализация (8.5, 9.4, 12.1, 12.6.1) объекта области имен пространства делается до первое изложение основного. Если инициализация откладывается до некоторых момент времени после первого изложение основного, должно произойти перед первым использованием любой функции или объект, определенный в том же Единица перевода как объект, который будет инициализирована

Вопрос 2: как получить эквивалент ключевых слов Delphi initialization и finalization?

Есть два варианта. Первое упомянуто другими авторами, и я не хочу копировать их ответы: объявите объект в определенной области ( единица перевода или пространство имен), и его конструктор и деструктор будут называться 'sometime'; там работаю.

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

Второй вариант также зависит от компилятора. Вы используете Delphi, так что я правильно понимаю, что вы используете C ++ Builder для компиляции своего кода C ++? Если это так, C ++ Builder и некоторые другие компиляторы поддерживают #pragma startup и #pragma exit pragmas . Эти прагмы вызывают метод в определенное время, когда ваша программа запускается или закрывается.

Лично я считаю это более подходящим решением по двум причинам:

  • Он точно указывает, когда что-то произойдет, и я вижу это написано вниз в коде

  • Позволяет позвонить функция вместо использования конструктор или деструктор. Это эстетически чище и позволяет писать, скажем, initialization() и finalization() методы, которые выполнять свою работу. Это, вероятно, приближает вас к синтаксису Delphi настолько, насколько это возможно.

Вы можете использовать эти прагмы для вызова процедуры (которая не принимает параметров и возвращает void), а также при необходимости указать, когда это должно произойти, используя число от 64 до 255. Это нужно делать только в том случае, если порядок инициализации или финализация имеет значение. Первый номер называется первым, а приоритеты от 0 до 63 зарезервированы. Например:

void initialization(void) { foo = 3; bar = 5; /* Do useful work here */ }
#pragma startup initialization 200

void finalization(void) { foo = 0; bar = 0; /* Do useful work here */ }
#pragma exit finalization 200

Цепочка вызовов управляется компоновщиком, и вы можете столкнуться с проблемами, если используете более специфичные для компилятора конструкции, такие как слабая упаковка , но в целом этот метод я бы порекомендовал.

3 голосов
/ 10 декабря 2010

В C ++ пары конструктор / деструктор обычно используются для такого рода вещей.Будьте осторожны при использовании статических объектов.Если вы хотите это сделать, вам следует прочитать две вещи:

  1. Что такое «фиаско статического порядка инициализации»?

  2. Как предотвратить «фиаско статического порядка инициализации»?

2 голосов
/ 09 декабря 2010

В классе есть конструкторы и деструкторы, которые вы можете использовать для инициализации и очистки.

Я думаю, что ближе всего к "единицам кода" в C ++ есть классы.

1 голос
/ 09 декабря 2010

Как правило, в C ++ он воспринимается как запах кода, чтобы иметь глобальное состояние, которое требует построения или уничтожения, и даже если бы у вас это было, вы бы просто объявили класс, который делает это в своем конструкторе, и определили глобальный экземпляр файла. этого.

1 голос
/ 09 декабря 2010

Напишите класс с конструктором (initialization код) и деструктором (finalization код).Объявите одноэлементный экземпляр этого класса;конструктор будет вызываться при запуске, а деструктор перед завершением работы программы.

0 голосов
/ 10 декабря 2010

Ближайшая особенность C ++ - это статические переменные (в частности, статические переменные-члены).

// A.h
class A
{
public:

private:
    static int someValue;
};

// A.cpp
int A::someValue = 2;

Статическая переменная инициализируется при запуске программы.Для статических членов не существует автоматической процедуры «завершения» (вам нужно написать собственную функцию очистки и вызвать ее).

0 голосов
/ 09 декабря 2010

В C ++ вы называете конструктор (эквивалентный вашему деструктору) с тем же именем вашего класса, а деструктор с тем же именем вашего класса с префиксом тильды (~):

Class Point {
    public:
    Point() {  }
    ~Point() { }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...