где хранить typedef, если бы я повторил typedef - PullRequest
3 голосов
/ 13 июля 2011

Скажите, у меня есть три файла

//first.h
typedef typename std::map<Vertex_t*,Vd_t> MapVertexVd_t;
//the graph class and ...
//other useful things related to a graph class

//second.h
#include "first.h"
class analyzeGraph {
MapVertexVd_t mapVertexVd;

public:
void fillMap();
};

//second.cpp
#include "second.h"
void analyzeGraph::fillMap()
{
//
}

Теперь вопрос, я должен поставить:

typedef typename std::map<Vertex_t*,Vd_t> MapVertexVd_t;

в файлах second.h и second.cpp для ясности. Я чувствую, что я запутался через некоторое время в моем коде слишком много typedef и typename.

Ответы [ 5 ]

5 голосов
/ 13 июля 2011

Я считаю, что в зависимости от обстоятельств они работают хорошо:

  • Для typedef, используемых во многих файлах, поместите их в общий заголовочный файл (возможно, с предварительными объявлениями и т. Д.)
  • Для typedef, используемых только несколькими функциями или методами (в объявлении), поместите их непосредственно перед первым соответствующим объявлением и убедитесь, что функции объявлены вместе.
  • Для typedef, используемых дляданные в классе или функции, поместите их в начале соответствующей области видимости, чтобы люди, читающие код, увидели их первыми.(И для классов сделайте видимость typedefs как можно более низкой - частные typedefs должны оставаться закрытыми.)
3 голосов
/ 13 июля 2011

В C89 или C99 (или предварительно стандартном C), повторение typedef в той же области является ошибкой компиляции, хотя это и неприятно. Однако C ++ более цивилизован и допускает «мягкое переопределение» (см. §7.1.3, ¶2, согласно Charles Bailey ). Несмотря на эту лицензию, одним из девизов Agile (или Pragmatic) Programming является «СУХОЙ: не повторяйся», что в этом контексте означает, что вы не должны писать typedef в более чем одном заголовке. Вы могли бы рассмотреть возможность создания заголовка zeroth.h, который включается каждым из других заголовков (first.h, second.h); он должен определить или переслать объявление типа Vertex_t; оно должно либо определять, либо включать объявление Vd_t (а также указывать тип MapVertexVd_t). Он также должен включать соответствующий стандартный заголовок (<map>), чтобы заголовок zeroth.h был автономным и мог использоваться без лишних слов любым кодом, который в этом нуждается.


Обратите внимание, что C11 также допускает мягкое переопределение типов:

ISO / IEC 9899: 2011 §6.7 Декларации

¶3 Если идентификатор не имеет связи, должно быть не более одного объявления идентификатора. (в деклараторе или спецификаторе типа) с той же областью действия и в том же пространстве имен, за исключением что:

  • имя typedef может быть переопределено для обозначения того же типа, что и в настоящее время, при условии, что тип не является изменяемым типом;

  • могут быть повторно объявлены, как указано в 6.7.2.3.

В отличие от этого, соответствующий раздел C99 гласит:

ISO / IEC 9899: 1999 §6.7 Декларации

§3 Если идентификатор не имеет связи, должно быть не более одного объявления идентификатора. (в деклараторе или спецификаторе типа) с той же областью действия и в том же пространстве имен, за исключением для тегов, как указано в 6.7.2.3.

3 голосов
/ 13 июля 2011

, если MapVertexVd_t используется только внутри analyGraph , лучше поместить typedef внутри класса analysisGraph .

3 голосов
/ 13 июля 2011

Нет, убедитесь, что объявления не дублируются.

То, как вы сделали это сейчас, на самом деле очень хорошо - у вас есть отдельный H-файл с typedef, и он включен везде:используется.Вот как это должно быть.

Проблема с дублированием состоит в том, что некоторым компиляторам это может не понравиться, даже если они идентичны.Если в какой-то момент вы должны изменить typedef - тогда вы в полном беспорядке.Вот почему вы должны избегать дублирования.

2 голосов
/ 13 июля 2011

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

Мое простое правило: определите его там, где оно имеет смысл . Во многих случаях это будет вместе с некоторыми из связанных типов (возможно, с определением Vertex_t) и использовать разумные имена для typedef, которые указывают, что это такое. Только если вы не знаете, что такое Vertex_t или Vd_t, вам нужно будет вернуться и проверить, что такое MapVertexVd_t, и тогда наличие локальной typedef также не поможет (я не знаю, что Vertex_t или Vd_t представляют, но выбирают разумные имена, которые будут звонить в колокольчик относительно того, что это за тип и какие операции вы можете над ним выполнять).

...