Declare frente ponteiros-to-estruturas em C ++
-
08-07-2019 - |
Pergunta
Eu estou usando uma biblioteca parte 3 que tem uma declaração como esta:
typedef struct {} __INTERNAL_DATA, *HandleType;
E eu gostaria de criar uma classe que leva um HandleType no construtor:
class Foo
{
Foo(HandleType h);
}
sem incluindo o cabeçalho que define HandleType . Normalmente, eu apenas voltada para o declarar tal tipo, mas eu não consigo descobrir a sintaxe para isso. Eu realmente quero dizer algo como:
struct *HandleType;
Mas que diz "identificador esperado antes *" no GCC. A única solução que vejo é para escrever a minha classe como este:
struct __INTERNAL_DATA;
class Foo
{
Foo(__INTERNAL_DATA *h);
}
Mas isso depende de detalhes internos da biblioteca. Ou seja, ele usa o __INTERNAL_DATA nome, que é um detalhe de implementação.
Parece que ele deveria ser possível encaminhar-declare HandleType (parte da API pública) sem usar __INTERNAL_DATA (parte da implementação da biblioteca.) Alguém sabe como?
EDIT:. Adicionado mais detalhes sobre o que eu estou procurando
Solução
Update:
Eu estou usando-o no CPP implementação de Foo, mas eu quero evitar incluí-lo na minha .h cabeçalho para Foo. Talvez eu esteja apenas sendo muito pedante? :)
Sim, você está :) Vá em frente com a declaração para a frente.
Se HandleType é parte da interface deve haver um cabeçalho declarando que. Use esse cabeçalho.
Seu problema é ainda uma vaga um. Você está tentando proteger contra algo que você não pode.
Você pode adicionar a seguinte linha para a biblioteca cliente:
typedef struct INTERNAL_DATA *HandleType;
mas, se o nome / estrutura mudanças que você pode estar em algum maldade casting.
Tente modelos:
template <class T>
class Foo
{
Foo(T h);
};
declaração para a frente é bom. Se você estiver indo para ponteiros de uso ou referências que você só precisa de uma declaração de classe (__INTERNAL_DATA
) no espaço. No entanto, se você estiver indo para usar uma função membro ou um objeto que você terá de incluir o cabeçalho.
Outras dicas
Se o tipo está em uma biblioteca parte 3, em seguida, a grande vantagem de declaração para a frente (isolando reconstruções devido a mudanças no cabeçalhos) é efetivamente perdido.
Se você está preocupado com o tempo de compilação (é um cabeçalho considerável), então talvez você pode colocá-lo em um cabeçalho pré-compilado ou apenas incluir o cabeçalho relevante de uma biblioteca.
por exemplo. muitos cabeçalhos biblioteca parecer
// library.h
#include "Library/Something.h"
#include "Library/SomethingElse.h"
typedef struct {} __INTERNAL_DATA, *HandleType;
Se ele é definido como aquele (todos em uma linha), então __INTERNAL DATA é tanto uma parte da interface pública como HandleType.
No entanto, eu não acho que __INTERNAL_DATA
realmente existe. Mais do que provável, HandleType é realmente (internamente) um int. Esta definição estranho é apenas uma maneira de defini-lo de modo que é do mesmo tamanho que um int, mas distintas, de modo que o compilador dará um erro se você tentar passar um int onde você deveria passar um HandleType. O fornecedor da biblioteca poderia facilmente ter definiu como "int" ou "void *", mas desta forma podemos obter algum tipo de verificação.
Assim __INTERNAL_DATA
é apenas uma convenção e não vai mudar.
UPDATE: O texto acima foi um pouco de um arroto mental, ... OK, __INTERNAL_DATA
definitivamente não existe. Sabemos que isso é um fato, porque podemos ver a sua definição como um struct vazio. Eu estou indo supor que a biblioteca 3rd-party usos "C" ligação externa (sem nome managling), caso em que, basta copiar o typedef -. Ele vai ficar bem
Dentro da própria biblioteca, HandleType irá ter uma definição completamente diferente; talvez int
, talvez "MyStruct struct {.......} *".
Se você realmente, realmente, realmente não quero expor _INTERNAL_DATA para o chamador então sua única opção real é usar typedef void * HandleType ; Em seguida, dentro de sua biblioteca que você pode fazer o que quiser, incluindo mudando toda a implementação de * HandleType.
Basta criar uma função auxiliar para acesso que dados real.
inline _INTERNAL_DATA* Impl(HandleType h) {
return static_cast<_INTERNAL_DATA*>(h);
}
Eu não tenho certeza do que você está indo para, mas a seguir irá funcionar sem incluir o arquivo de cabeçalho real:
// foo.h
class Foo
{
public:
template<typename T>Foo(T* h) { /* body of constructor */ }
};
Mind você, você ainda tem que ter acesso aos membros públicos de __INTERNAL_DATA
dentro do corpo do construtor.
edit:. como fora apontado por James Curran, a estrutura __INTERNAL_DATA
não possui membros, para que ele possa ser usado, como acima, sem problemas