2014-11-07 6 views
1

Я пишу несколько классов, которые используют типы и функции из другой библиотеки. Эта библиотека требует инициализации перед вызовом любой другой функции. Кроме того, классы используют типы данных, предоставляемые библиотекой, которые также должны быть инициализированы перед использованием (но после инициализации библиотеки). Классы выглядят следующим образом:Обход вызова конструктора базового класса

class A { 
public: 
    A() { init(); } 
    void init() { lib_type_init(&t); } 
    // ... 
    // Other methods 
    // ... 
protected: 
    lib_type t; 
    // ... 
    // Other fields 
    // ... 
} 

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

class global_A : public A { 
public: 
    global_A() {} 
} 

Однако, это еще вопрос, потому что в C++, базовый класс конструкторы называются производными классами, если конструктор не имеет никаких аргументов. Это, очевидно, вызывает проблемы во время выполнения, когда вызываются глобальные конструкторы объектов (он пытается вызвать функцию init библиотеки и выдает ошибку, поскольку сама библиотека не инициализируется).

Эти классы имеют относительно большое количество методов, и я не хочу, чтобы мой код взорвался по размеру. С учетом сказанного, есть ли лучший подход к решению этого вопроса, кроме полного копирования A в global_A без конструктора?

+0

@dasblinkenlight Я не совсем понимаю, как ваше предложение решает что угодно. У меня много глобальных и локальных экземпляров 'A' (используется во многих функциях diff). Я не хочу, чтобы вызывать 'init()' во всех локальных экземплярах, потому что он загрязняет мой код. –

+0

@dasblinkenlight Каждый экземпляр 'A' должен вызывать' init() '. Он предназначен для инициализации внутреннего типа данных в соответствии со спецификациями внешней библиотеки. –

+0

Я не совсем понимаю вопрос.Ваши локальные экземпляры должны вызывать 'init()', и существует какой-то отдельный 'init()', который должен запускаться только один раз до того, как будут созданы все глобальные экземпляры? – AndyG

ответ

1

Похоже, что A должен наследовать от global_A, а не наоборот.

Хотя, возможно, вы захотите придумать лучшее имя, чем global_A.

2

По умолчанию конструктор по умолчанию всегда вызывает init() автоматически. Чтобы иметь общедоступную функцию init(), имеет смысл только в том случае, если существуют другие конструкторы, которые не звонят init(). Вы просто должны вызвать соответствующий конструктор из списка элемента инициализатора производного класса:

global_A::global_A(): A(some_arguments) {} 

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

global_A& global() { 
    static global_A rc; 
    return rc; 
} 

кроме этого, не то, что вы, вероятно, лучше от ** не * имеют какие-либо глобальные объекты, в первую очередь! В общем, любое глобальное состояние делает код трудным для тестирования и вызывает проблему при параллелизме.

0

Создайте конструктор не по умолчанию в базовом классе, который не вызывает init(). Явно вызовите этот конструктор не по умолчанию в списке инициализации конструктора для вашего глобального класса.

Смежные вопросы