Em quais cenários é melhor usar um struct
vs a class
em C ++?
Em quais cenários é melhor usar um struct
vs a class
em C ++?
Respostas:
As diferenças entre a class
e a struct
em C ++ são que as estruturas têm public
membros e bases padrão e as classes têm private
membros e bases padrão . Ambas as classes e estruturas podem ter uma mistura de public
, protected
e private
membros, podem usar herança e podem ter funções de membro.
Eu recomendaria o uso de estruturas como estruturas simples de dados antigos, sem nenhum recurso semelhante a uma classe, e o uso de classes como estruturas agregadas de dados com private
funções de dados e membros.
Como todo mundo observa, existem realmente apenas duas diferenças de idioma reais:
struct
padrões para acesso público e class
padrões para acesso privado.struct
padrão é a public
herança e o class
padrão é a private
herança. (Ironicamente, como em muitas coisas em C ++, o padrão é inverso: public
herança é de longe a escolha mais comum, mas as pessoas raramente declaram struct
s apenas para economizar ao digitar a public
palavra-chave " ".Mas a diferença real na prática é entre um class
/ struct
que declara um construtor / destruidor e outro que não. Existem certas garantias para um tipo de POD com "dados antigos simples", que não se aplicam mais depois que você assume a construção da classe. Para manter essa distinção clara, muitas pessoas deliberadamente usam apenas struct
s para tipos de POD e, se quiserem adicionar algum método, use class
es. A diferença entre os dois fragmentos abaixo não tem sentido:
class X
{
public:
// ...
};
struct X
{
// ...
};
(Aliás, aqui está um tópico com algumas boas explicações sobre o que "tipo de POD" realmente significa: o que são tipos de POD em C ++? )
struct
ou class
não tem influência sobre se seu objeto é POD ou se deve definir um construtor / destruidor de cópia. As funções de membro também não têm influência em algo que é POD. Como eu re-ler o que você escreveu, eu vejo que você não está sugerindo o contrário, mas a redacção actual é confuso
Existem muitas idéias erradas nas respostas existentes.
Ambos class
e struct
declarar uma classe.
Sim, pode ser necessário reorganizar as palavras-chave de modificação de acesso dentro da definição de classe, dependendo da palavra-chave usada para declarar a classe.
Mas, além da sintaxe, a única razão para escolher uma sobre a outra é a convenção / estilo / preferência.
Algumas pessoas gostam de usar a struct
palavra - chave para classes sem funções-membro, porque a definição resultante "se parece" com uma estrutura simples de C.
Da mesma forma, algumas pessoas gostam de usar a class
palavra - chave para classes com funções e private
dados de membros , porque diz "classe" e, portanto, parece exemplos de seu livro favorito sobre programação orientada a objetos.
A realidade é que isso depende totalmente de você e sua equipe, e isso não fará nenhuma diferença no seu programa.
As duas classes a seguir são absolutamente equivalentes em todos os aspectos, exceto no nome:
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
Você pode até mudar as palavras-chave ao declarar novamente:
class Foo;
struct Bar;
(embora isso interrompa as compilações do Visual Studio devido à não conformidade, para que o compilador emita um aviso quando você fizer isso.)
e as seguintes expressões são avaliadas como verdadeiras:
std::is_class<Foo>::value
std::is_class<Bar>::value
Observe, porém, que você não pode mudar as palavras-chave ao redefinir ; isso ocorre apenas porque (de acordo com a regra de uma definição) as definições de classe duplicadas nas unidades de tradução devem "consistir na mesma sequência de tokens" . Isto significa que você não pode mesmo trocar const int member;
com int const member;
, e não tem nada a ver com a semântica class
oustruct
.
class foo { public: ... };
e outra que possa ser struct foo { ... };
mantida verdadeira, de acordo com a afirmação "absolutamente equivalente". É lógico que as declarações incompletas struct foo;
e class foo;
são intercambiáveis. Eles não especificam o corpo da classe e, portanto, não falam nada ao layout de acesso.
Foo
e Bar
ainda são equivalentes / tipos idênticos. Eu tive a certeza de dizer "ao redeclarar " e dar um exemplo. Venha para pensar sobre isso, vou esclarecer isso na resposta para ter certeza de que não estou enganando as pessoas em UB
A única vez em que uso uma struct em vez de uma classe é ao declarar um functor antes de usá-lo em uma chamada de função e quero minimizar a sintaxe por uma questão de clareza. por exemplo:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
No C ++ FAQ Lite :
Os membros e as classes base de uma estrutura são públicos por padrão, enquanto na classe, eles são privados. Nota: você deve tornar suas classes base explicitamente públicas, privadas ou protegidas, em vez de confiar nos padrões.
struct e classe são funcionalmente equivalentes.
OK, chega dessa conversa limpa e estridente. Emocionalmente, a maioria dos desenvolvedores faz uma forte distinção entre uma classe e uma estrutura. Uma estrutura simplesmente parece uma pilha aberta de bits com muito pouco em termos de encapsulamento ou funcionalidade. Uma classe se sente como um membro vivo e responsável da sociedade, com serviços inteligentes, uma forte barreira de encapsulamento e uma interface bem definida. Como essa é a conotação que a maioria das pessoas já tem, você provavelmente deve usar a palavra-chave struct se tiver uma classe que possui muito poucos métodos e dados públicos (essas coisas existem em sistemas bem projetados!), Mas, caso contrário, você provavelmente deve usar a classe palavra-chave
Um lugar em que uma estrutura foi útil para mim é quando eu tenho um sistema que está recebendo mensagens de formato fixo (por exemplo, uma porta serial) de outro sistema. Você pode converter o fluxo de bytes em uma estrutura que define seus campos e, em seguida, acessar facilmente os campos.
typedef struct
{
int messageId;
int messageCounter;
int messageData;
} tMessageType;
void processMessage(unsigned char *rawMessage)
{
tMessageType *messageFields = (tMessageType *)rawMessage;
printf("MessageId is %d\n", messageFields->messageId);
}
Obviamente, é a mesma coisa que você faria em C, mas acho que a sobrecarga de ter que decodificar a mensagem em uma classe geralmente não vale a pena.
operator >>
em uma classe em vez de escrever a processMessage
função, o que tornaria o seu C ++ olhar mais como adequada C ++ e menos como C.
__packed__
campos de bits fixos, uma estrutura e ter uma implementação ifdef com reconhecimento de endian (você precisa alterar a ordem em uma máquina em que a endianess é oposta à fonte de dados externa está fornecendo). Não é bonito, mas eu costumava empacotar / descompactar registros para periféricos remotos em plataformas embarcadas de maneira portátil.
char
tipo, que está isento de alias. No entanto, ainda há um problema, ainda que diferente: converter um char*
para um tipo diferente, se não houver realmente nenhum objeto do último tipo já inicializado nesse endereço, é UB, pois viola as regras da vida útil. No entanto, mesmo que o tipo de destino seja trivialmente construtível, apenas ter memória alocada não é suficiente para o C ++ permitir formalmente tratar essa memória como esse tipo.
Você pode usar "struct" no C ++ se estiver escrevendo uma biblioteca cujos internos são C ++, mas a API pode ser chamada pelo código C ou C ++. Você simplesmente cria um único cabeçalho que contém estruturas e funções globais da API que você expõe ao código C e C ++ como este:
// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif
// Put your C struct's here
struct foo
{
...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;
// Put your C API functions here
void bar(foo *fun);
#ifdef __cpp
}
#endif
Em seguida, você pode escrever uma barra de função () em um arquivo C ++ usando o código C ++ e torná-lo acessível a partir de C e os dois mundos podem compartilhar dados através da estrutura declarada. É claro que existem outras advertências ao misturar C e C ++, mas este é um exemplo simplificado.
Como todo mundo diz, a única diferença real é o acesso padrão. Mas eu particularmente uso o struct quando não quero nenhum tipo de encapsulamento com uma classe de dados simples, mesmo que eu implemente alguns métodos auxiliares. Por exemplo, quando eu preciso de algo assim:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
Para responder à minha própria pergunta (sem vergonha): Como já mencionado, os privilégios de acesso são a única diferença entre eles no C ++.
Costumo usar uma estrutura apenas para armazenamento de dados. Permitirei que ele obtenha algumas funções auxiliares se facilitar o trabalho com os dados. No entanto, assim que os dados exigirem controle de fluxo (ou seja, getters / setters que mantêm ou protegem um estado interno) ou começarem a adquirir qualquer funcionalidade importante (basicamente mais parecida com um objeto), eles serão 'atualizados' para uma classe para melhor comunicar a intenção.
Estruturas ( PODs , mais geralmente) são úteis quando você fornece uma interface compatível com C com uma implementação C ++, uma vez que são portáveis através das bordas da linguagem e dos formatos do vinculador.
Se isso não é uma preocupação para você, suponho que o uso de "struct" em vez de "classe" seja um bom comunicador de intenções (como o @ZeroSignal disse acima). As estruturas também têm uma semântica de cópia mais previsível; portanto, são úteis para os dados que você deseja gravar em mídia externa ou enviar através da conexão.
Estruturas também são úteis para várias tarefas de metaprogramação, como modelos de características que apenas expõem vários tipos de tipos dependentes:
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
... Mas isso é apenas tirar vantagem do nível de proteção padrão do struct ser público ...
Para C ++, realmente não há muita diferença entre estruturas e classes. A principal diferença funcional é que os membros de uma estrutura são públicos por padrão, enquanto eles são privados por padrão nas classes. Caso contrário, no que diz respeito ao idioma, eles são equivalentes.
Dito isto, eu costumo usar estruturas em C ++, como faço em C #, semelhante ao que Brian disse. As estruturas são simples contêineres de dados, enquanto as classes são usadas para objetos que precisam atuar nos dados, além de apenas mantê-los.
Eles são praticamente a mesma coisa. Graças à magia do C ++, uma estrutura pode conter funções, usar herança, criada usando "new" e assim por diante, como uma classe
A única diferença funcional é que uma classe começa com direitos de acesso privado, enquanto uma estrutura começa com público. Esta é a compatibilidade com manutenção anterior com C.
Na prática, sempre usei estruturas como titulares de dados e classes como objetos.
Como outros apontaram
Há uma recomendação clara sobre quando usar qual da Stroustrup / Sutter:
No entanto, lembre-se de que não é aconselhável encaminhar declarar sth. como uma classe ( class X;
) e defina-a como struct ( struct X { ... }
). Pode funcionar em alguns vinculadores (por exemplo, g ++) e pode falhar em outros (por exemplo, MSVC), portanto você se encontrará no inferno dos desenvolvedores.
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }
não apenas compila e executa com o MSVC 2017, mas também produz um aviso claro que Foo
foi declarado como struct
definido class
. Mas também me lembro claramente que custou à nossa equipe meio dia para encontrar esse bug estúpido. Não tenho certeza de qual versão do MSVC usamos antes.
class
ou struct
em uma declaração direta, e os dois são livremente intercambiáveis de acordo com o padrão (embora seja sabido que o VS avisa; eu sempre assumi que isso era apenas para evitar aparentes erros do programador). Algo não cheira bem aqui. Tem certeza de que não foi um erro de violação do ODR?
struct
-forward para class
-forward, os problemas desapareceram. A partir de hoje, acho estranho também. Ficaria feliz se você pudesse lançar alguma luz sobre isso.
Os membros da classe são privados por padrão.
class test_one {
int main_one();
};
É equivalente a
class test_one {
private:
int main_one();
};
Então, se você tentar
int two = one.main_one();
Iremos receber um erro: main_one is private
porque não é acessível. Podemos resolvê-lo, inicializando-o, especificando que é um público, ou seja,
class test_one {
public:
int main_one();
};
Uma estrutura é uma classe em que os membros são públicos por padrão.
struct test_one {
int main_one;
};
O meio main_one
é privado, isto é
class test_one {
public:
int main_one;
};
Eu uso estruturas para estruturas de dados em que os membros podem ter qualquer valor, é mais fácil assim.
Uma vantagem do struct
excesso class
é que ele salva uma linha de código, se estiver aderindo aos "primeiros membros públicos, depois privados". Nesta perspectiva, considero a palavra class
- chave inútil.
Aqui está outro motivo para usar apenas struct
e nunca class
. Algumas diretrizes de estilo de código para C ++ sugerem o uso de letras pequenas para macros de função, a lógica é que, quando a macro é convertida em uma função embutida, o nome não precisa ser alterado. O mesmo aqui. Você tem sua estrutura agradável no estilo C e, um dia, descobre que precisa adicionar um construtor ou algum método de conveniência. Você muda para a class
? Em toda parte?
Distinguir entre struct
es e class
es é muito complicado, atrapalhando o modo de fazer o que deveríamos estar fazendo - programação. Como muitos dos problemas do C ++, ele surge do forte desejo de compatibilidade com versões anteriores.
class
? Você achou que uma classe definida com a struct
palavra - chave não pode ter funções-membro ou construtor?
joe()
deve ser definida com a class
palavra - chave? Toda classe com pelo menos 4 int
membros deve ser definida com a struct
palavra - chave?
struct
, agregados com métodos são definidos com class
". Muito aborrecimento.
eles são a mesma coisa com padrões diferentes (privado por padrão para class
e público por padrão para struct
), portanto, em teoria, eles são totalmente intercambiáveis.
então, se eu quiser apenas empacotar algumas informações para mover, uso uma struct, mesmo que eu coloque alguns métodos lá (mas não muitos). Se for algo opaco, em que o uso principal seria através de métodos, e não diretamente para os membros dos dados, eu uso uma classe completa.
Ambos struct
e class
são as mesmas sob o capô embora com diferentes padrões como a visibilidade, struct
o padrão é público e class
padrão é privado. Você pode alterar um para o outro com o uso apropriado de private
e public
. Ambos permitem herança, métodos, construtores, destruidores e todo o restante dos itens de uma linguagem orientada a objetos.
No entanto, uma enorme diferença entre os dois é que, struct
como uma palavra-chave é suportada em C, enquanto class
não é. Isso significa que é possível usar a struct
em um arquivo de inclusão que pode estar #include
em C ++ ou C, desde que struct
seja um estilo C simples struct
e tudo o mais no arquivo de inclusão seja compatível com C, ou seja, nenhuma palavra-chave específica em C ++, como private
,public
, nenhuma métodos, sem herança, etc. etc. etc.
O estilo CA struct
pode ser usado com outras interfaces que suportam o uso do estilo C struct
para transportar dados pela interface.
O estilo AC struct
é um tipo de modelo (não um modelo C ++, mas um padrão ou estêncil) que descreve o layout de uma área de memória. Ao longo dos anos as interfaces utilizável a partir C e com o C plug-ins (aqui está olhando para você Java e Python e Visual Basic) foram criados alguns dos quais trabalho com estilo C struct
.
Tecnicamente, ambos são iguais em C ++ - por exemplo, é possível que uma estrutura tenha operadores sobrecarregados, etc.
Contudo :
Uso structs quando desejo passar informações de vários tipos simultaneamente. Uso classes quando estou lidando com um objeto "funcional".
Espero que ajude.
#include <string>
#include <map>
using namespace std;
struct student
{
int age;
string name;
map<string, int> grades
};
class ClassRoom
{
typedef map<string, student> student_map;
public :
student getStudentByName(string name) const
{ student_map::const_iterator m_it = students.find(name); return m_it->second; }
private :
student_map students;
};
Por exemplo, estou retornando um aluno struct nos métodos get ... () por aqui - aproveite.
Quando você escolheria usar struct e quando usar classe em C ++?
Eu uso struct
quando eu defino functors
e POD
. Caso contrário, eu uso class
.
// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
bool operator()(int first, int second)
{ return first < second; }
};
class mycompare : public std::binary_function<int, int, bool>
{
public:
bool operator()(int first, int second)
{ return first < second; }
};
std::binary_function<>
não é apenas obsoleta, o c ++ 17 até a remove.
Todos os membros da classe são privados por padrão e todos os membros da estrutura são públicos por padrão. A classe possui bases privadas padrão e o Struct possui bases públicas padrão. Struct no caso de C não pode ter funções de membro, enquanto no C ++ podemos adicionar funções de membro à estrutura. Além dessas diferenças, não acho nada surpreendente sobre elas.
Só uso o struct quando preciso reter alguns dados sem nenhuma função de membro associada a ele (para operar com os dados do membro) e acessar diretamente as variáveis de dados.
Por exemplo: Leitura / gravação de dados de arquivos e fluxos de soquete, etc. Passando argumentos de função em uma estrutura onde os argumentos de função são muitos e a sintaxe da função parece muito longa.
Tecnicamente, não há grande diferença entre classe e estrutura, exceto a acessibilidade padrão. Mais do que isso depende do estilo de programação de como você o usa.
Eu pensei que o Structs era destinado como uma Estrutura de Dados (como uma matriz de informações com vários dados) e as classes eram destinadas ao Empacotamento de Código (como coleções de sub-rotinas e funções).
:(
Eu nunca uso "struct" em C ++.
Eu nunca consigo imaginar um cenário em que você usaria uma estrutura quando quiser membros privados, a menos que esteja tentando deliberadamente confundir.
Parece que o uso de estruturas é mais uma indicação sintática de como os dados serão usados, mas prefiro criar uma classe e tentar explicitar isso em nome da classe ou através de comentários.
Por exemplo
class PublicInputData {
//data members
};
struct
já não seria bastante explícito de que os membros da classe serão, por padrão, públicos?