Желательно ли использовать extern, чтобы избежать зависимости заголовка? - PullRequest
3 голосов
/ 11 августа 2011

Я удалил два включения заголовка в блоке перевода, используя extern.Это целесообразно?

Моя конкретная ситуация: у меня есть класс с именем ParseTree, который накапливает Token*.ParseTree* является приватным членом Parser.

Изначально у меня были следующие строки в parse_tree.cc.

#include "parser.h"
#include "token.h"

После анализа моего кода я выделил две функции, которыефактически имел внешние зависимости и заменил включенные элементы следующим образом:

extern std::ostream& operator<<(std::ostream& out, const Token& t); // @token.h
extern bool hasPriority(const Token* p_tok1, Token* p_tok2); // @parser.h

Оба решения работают.Есть ли какие-то скрытые опасности, о которых я должен знать, выбирая extern over include?

Ответы [ 3 ]

8 голосов
/ 11 августа 2011

Если вы используете extern декларации, вы излишне повторяете себя, повторяя прототип функции везде, где вы ее используете. С файлом заголовка, если вы хотите изменить прототип, вам нужно изменить его только в одном месте.

Так что нет, не используйте extern, когда у вас уже есть подходящий заголовочный файл.

1 голос
/ 11 августа 2011

Обычно каждый уменьшает зависимости путем объявления классов вперед. Вот пример. Скажем, у нас есть два обязательных заголовка, parser.h и token.h, определенные следующим образом:

parser.h:

class Parser
{
public:
  void doFoo();
  void doBar();
  // ... lots of other stuff
};

token.h:

class Token
{
public:
  void doQuux();
  void doBaz();
  // ... continues for a while
};

Теперь, имея "пользователя, h", который использует эти два, вместо того, чтобы писать это как:

#include "parser.h"
#include "token.h"

void useParserAndToken( Parser &, Token & );

вы пишете

class Parser;
class Token;

void useParserAndToken( Parser &, Token & );

Таким образом, вы в итоге говорите, что есть классы Parser и Token, но как они точно определены, не имеет значения. Это приводит к более быстрой компиляции.

Чтобы уменьшить зависимости, вы обычно только заранее объявляете классы. С другой стороны, дублирование объявлений не имеет особого смысла.

1 голос
/ 11 августа 2011

Оба решения работают.Есть ли какие-то скрытые опасности, о которых я должен знать, выбирая extern over include?

Да.API может измениться, и компилятор не будет работать для вас, он будет работать против вас.

Научитесь использовать компилятор в ваших интересах.Нет, не только "СЕЙЧАС", я имею в виду в долгосрочной перспективе.В долгосрочной перспективе вы совершаете глупые ошибки, а не тогда, когда в вашей голове все свежо.Да, память вашего мозга как-то изменчива.

...