Isso não é aplicável apenas ao C ++, mas a qualquer linguagem que fornece estruturas e classes.
Jason Bunting
3
Ainda discordo - abordo essa questão semântica. Talvez haja algumas diferenças técnicas, mas semanticamente, elas não são. Estruturas são realmente úteis para criar tipos de valor, classes não.
Jason Bunting
4
Eu acredito que não há motivo sério para usar estruturas em C ++. Para mim, estruturas são outro "recurso" redundante do C ++ que existe apenas para compatibilidade com C, como typedefs. Isso não existiria se o C ++ não fosse tratado inicialmente como uma extensão do C e fosse projetado do zero, como Java. Em geral, acho que muitas das coisas mais estranhas sobre C ++ têm a ver com compatibilidade com C.
Kostas
5
Struct - Para POD (dados antigos simples) e toda a acessibilidade dos membros é pública. Classe - Quando você precisa de um melhor encapsulamento e precisa de funções membro para trabalhar com o estado da classe.
Navaneeth KN
4
Isso é verdade apenas por convenção. Não há diferença, além do encapsulamento padrão.
Dave Hillier
Respostas:
805
As diferenças entre a classe a structem C ++ são que as estruturas têm publicmembros e bases padrão e as classes têm privatemembros e bases padrão . Ambas as classes e estruturas podem ter uma mistura de public, protectede privatemembros, 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 privatefunções de dados e membros.
Uma estrutura sem modificadores ou métodos é chamada de estrutura POD, que existe como uma interface compatível com as bibliotecas C, uma vez que é (supostamente) garantida a disposição, como se fosse uma estrutura C. À parte essa exceção, a única diferença é como declarado.
workmad3 18/09/08
26
@ workmad3: O nome é enganador, mas 9/4 (C ++ 03) diz: "Uma estrutura POD é uma classe agregada que não possui membros de dados não estáticos do tipo estrutura não POD, união não POD (ou matriz de tais tipos) ou referência e não possui operador de atribuição de cópia definido pelo usuário nem destruidor definido pelo usuário ". Não há restrição no uso da chave de classe "struct" e nenhuma restrição no uso de "public" (consulte 8.5.1 / 1 para requisitos agregados). Esta não é uma diferença entre "struct" e "classe".
5
Seu uso de "agregado" pode ser mal compreendido, dada a definição do padrão. :)
3
De acordo com o livro "Principles and Practice" de Stroustrup: "as estruturas devem ser usadas principalmente onde os membros podem ter qualquer valor" (ou seja, onde nenhuma classe significativa invariável pode ser definida)
antibus
6
Claro que você pode usar classes ao interagir com C. Não há diferença entre classes e estruturas. Estruturas são classes; somente o acesso padrão é invertido de privado para público.
Sebastian Mach
230
Como todo mundo observa, existem realmente apenas duas diferenças de idioma reais:
structpadrões para acesso público e classpadrões para acesso privado.
Ao herdar, o structpadrão é a publicherança e o classpadrão é a privateherança. (Ironicamente, como em muitas coisas em C ++, o padrão é inverso: publicherança é de longe a escolha mais comum, mas as pessoas raramente declaram structs apenas para economizar ao digitar a publicpalavra-chave " ".
Mas a diferença real na prática é entre um class/ structque 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 structs para tipos de POD e, se quiserem adicionar algum método, use classes. 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 ++? )
Belo exemplo sobre as diferenças de herança: aqui .
Liran Orevi 13/09/10
8
Se você usa structou classnã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
David Stone
1
@DavidStone Basicamente, supõe-se que as estruturas de POD sejam compatíveis com versões anteriores do código C e, portanto, basicamente sejam projetadas apenas como estruturas de estilo C.
Justin Time - Restabelece Monica
3
A parte "real diferença" desta resposta está totalmente errada.
Juanchopanza
178
Existem muitas idéias erradas nas respostas existentes.
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 structpalavra - 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 classpalavra - chave para classes com funções e privatedados 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:
structFoo{int x;};classBar{public:int x;};
Você pode até mudar as palavras-chave ao declarar novamente:
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 classoustruct .
Isso foi muito informativo e, honestamente, minha resposta favorita. Todos os outros estão tratando-os como entidades separadas, quando embaixo do capô são iguais. Gostaria de saber se uma definição de struct no ambiente do Arduino é considerada uma classe cpp, visto que é compilada usando g ++.
24717 Benjamin
4
@ Ben Claro que é. O compilador Arduino compila C ++; esse é o fim disso.
Underscore_d
7
Portanto, se estou entendendo direito: contanto que seus modificadores de visibilidade sejam explícitos, não omitidos, isso não importa. Você pode escrever um enorme aplicativo C ++ usando nada além de estruturas; ou você pode passar e alterar todos os casos de struct para classe. Contanto que você não esteja usando a visibilidade padrão, os aplicativos serão exatamente os mesmos.
Ryan Lundy
Não estou convencido de que uma unidade de tradução de um programa C ++ possa ter a declaração completa 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.
Kaz
@Kaz: Você está certo - se as definições eram literalmente do mesmo tipo, elas devem ser lexicamente idênticas para que o comportamento seja bem definido. A estrutura de chave e classe-chave são de outro modo logicamente embora permutável (onde a semântica não são afectados), e Fooe Barainda 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
Lightness Races in Orbit
54
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:
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
Eu não entendo por que eles estão afirmando que struct e classe são funcionalmente o mesmo, mas dizendo preferir a um sobre o outro, em certos casos, sem qualquer raciocínio ..
Deetz
3
O motivo é a convenção. O compilador não se importa com o que você usa, mas outro desenvolvedor que olha o seu código terá mais facilidade para entender o que você quis dizer.
22417 Tal Pressman
3
@deetz: O terceiro parágrafo inteiro está fundamentado.
Lightness Races em órbita
Uau, vindo da 'velha escola', eu não fazia ideia de que uma estrutura poderia ter métodos e até herança. Eu sempre usei struct para usar apenas dados apenas sem métodos e geralmente é quando lidamos com código de API que precisa da estrutura. As estruturas também podem suportar herança múltipla?
Paul McCarthy
21
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.
Ou você poderia apenas implementar operator >>em uma classe em vez de escrever a processMessagefunção, o que tornaria o seu C ++ olhar mais como adequada C ++ e menos como C.
Nick Bastin
1
Além do fato de não ser portátil entre sistemas diferentes, isso viola as regras de alias, portanto não é garantido que funcione mesmo em uma única arquitetura.
Underscore_d
@underscore_d Isso pode funcionar independentemente da plataforma (mas não do compilador), mas você deve usar __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.
Crasic
1
@jacwah Huh, bom ponto. O alias não será um problema aqui, porque um dos ponteiros é um chartipo, 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.
underscore_d
19
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 herestruct foo
{...};// NOTE: the typedef is used because C does not automatically generate// a typedef with the same name as a struct like C++.typedefstruct foo foo;// Put your C API functions herevoid 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.
Melhor resposta adequada. A compatibilidade C é realmente a razão mais importante. todas as outras coisas, como acesso padrão, são esotéricas.
Valentin Heinitz
16
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:
+1 por dar um exemplo de uma estrutura com algumas funções-membro que não parecem ter "retirado a estrutura".
einpoklum
9
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 ...
Esse não é o uso correto do POD. Uma estrutura (ou classe) pode ser uma estrutura POD se (e somente se) contiver apenas membros POD.
Martin Iorque
4
"semântica previsível de cópia": a semântica é a mesma da classe (e tem os mesmos problemas (cópia superficial)).
Martin Iorque
2
Nesta publicação, você acreditaria (espero que por acidente) que todas as estruturas são PODs. Isto não é de todo verdade. Espero que as pessoas não sejam enganadas por isso.
22714 Michael Michael Dorst
8
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.
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.
Você pode descrever esses problemas do vinculador?
Lightness Races in Orbit
@LightnessRacesinOrbit Não posso, infelizmente. Eu nem sou capaz de criar um exemplo. O trivial 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 Foofoi declarado como structdefinido 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.
pasbi 23/02/19
O vinculador nem deveria saber se você usou classou structem 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?
Não me lembro exatamente. O problema não ocorreu diretamente em um aplicativo, mas em uma biblioteca usada em um gtest. Eu apenas sei que o vinculador produziu erros incompreensíveis (LNK ???). Depois que eu substituí o 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.
23719 pasbi
3
Classe.
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 privateporque não é acessível. Podemos resolvê-lo, inicializando-o, especificando que é um público, ou seja,
class test_one {public:int main_one();};
Struct.
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 structexcesso 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 structe 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 structes e classes é 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.
Por que você precisaria alterá-lo para a class? Você achou que uma classe definida com a structpalavra - chave não pode ter funções-membro ou construtor?
Lightness Races em órbita
@LightnessRacesinOrbit por causa da 1. consistência e 2. alguns analisadores estáticos se queixam da violação do 1.
Vorac
Isso não segue. Quais outras "consistências" você adere? Toda classe com um membro chamado joe()deve ser definida com a classpalavra - chave? Toda classe com pelo menos 4 intmembros deve ser definida com a structpalavra - chave?
Lightness Races em órbita em
@LightnessRacesinOrbit Estou me referindo ao idioma "Agregados de POD são definidos com struct, agregados com métodos são definidos com class". Muito aborrecimento.
Vorac 28/02/19
2
eles são a mesma coisa com padrões diferentes (privado por padrão para classe 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.
Estruturas por padrão têm acesso público e classes por padrão têm acesso privado.
Pessoalmente, uso estruturas para objetos de transferência de dados ou como objetos de valor. Quando usado como tal, declaro todos os membros como const para evitar modificações por outro código.
Ambos structe classsão as mesmas sob o capô embora com diferentes padrões como a visibilidade, structo padrão é público e classpadrão é privado. Você pode alterar um para o outro com o uso apropriado de privatee 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, structcomo uma palavra-chave é suportada em C, enquanto classnão é. Isso significa que é possível usar a structem um arquivo de inclusão que pode estar #includeem C ++ ou C, desde que structseja um estilo C simples structe 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 structpode ser usado com outras interfaces que suportam o uso do estilo C structpara 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.
Quando você escolheria usar struct e quando usar classe em C ++?
Eu uso structquando eu defino functorse POD. Caso contrário, eu uso class.
// '()' is public by default!struct mycompare :public std::binary_function<int,int,bool>{booloperator()(int first,int second){return first < second;}};class mycompare :public std::binary_function<int,int,bool>{public:booloperator()(int first,int second){return first < second;}};
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 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.
De acordo com mim, uma "indicação sintática de como os dados serão usados" é uma boa razão para usar uma estrutura, especialmente se a alternativa for usar um comentário ou um nome no nome da classe.
Viktor Sehr
2
Declarar um structjá não seria bastante explícito de que os membros da classe serão, por padrão, públicos?
Respostas:
As diferenças entre a
class
e astruct
em C ++ são que as estruturas têmpublic
membros e bases padrão e as classes têmprivate
membros e bases padrão . Ambas as classes e estruturas podem ter uma mistura depublic
,protected
eprivate
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.fonte
Como todo mundo observa, existem realmente apenas duas diferenças de idioma reais:
struct
padrões para acesso público eclass
padrões para acesso privado.struct
padrão é apublic
herança e oclass
padrão é aprivate
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 declaramstruct
s apenas para economizar ao digitar apublic
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 apenasstruct
s para tipos de POD e, se quiserem adicionar algum método, useclass
es. A diferença entre os dois fragmentos abaixo não tem sentido:(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 ++? )
fonte
struct
ouclass
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 é confusoExistem muitas idéias erradas nas respostas existentes.
Ambos
class
estruct
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 eprivate
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:
Você pode até mudar as palavras-chave ao declarar novamente:
(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:
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;
comint const member;
, e não tem nada a ver com a semânticaclass
oustruct
.fonte
class foo { public: ... };
e outra que possa serstruct foo { ... };
mantida verdadeira, de acordo com a afirmação "absolutamente equivalente". É lógico que as declarações incompletasstruct foo;
eclass foo;
são intercambiáveis. Eles não especificam o corpo da classe e, portanto, não falam nada ao layout de acesso.Foo
eBar
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 UBA ú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:
fonte
No C ++ FAQ Lite :
fonte
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.
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.
fonte
operator >>
em uma classe em vez de escrever aprocessMessage
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 umchar*
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:
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.
fonte
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:
fonte
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.
fonte
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:
... Mas isso é apenas tirar vantagem do nível de proteção padrão do struct ser público ...
fonte
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.
fonte
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.
fonte
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.fonte
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 queFoo
foi declarado comostruct
definidoclass
. 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
oustruct
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 paraclass
-forward, os problemas desapareceram. A partir de hoje, acho estranho também. Ficaria feliz se você pudesse lançar alguma luz sobre isso.Classe.
Os membros da classe são privados por padrão.
É equivalente a
Então, se você tentar
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,Struct.
Uma estrutura é uma classe em que os membros são públicos por padrão.
O meio
main_one
é privado, isto éEu uso estruturas para estruturas de dados em que os membros podem ter qualquer valor, é mais fácil assim.
fonte
Uma vantagem do
struct
excessoclass
é que ele salva uma linha de código, se estiver aderindo aos "primeiros membros públicos, depois privados". Nesta perspectiva, considero a palavraclass
- chave inútil.Aqui está outro motivo para usar apenas
struct
e nuncaclass
. 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 aclass
? Em toda parte?Distinguir entre
struct
es eclass
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.fonte
class
? Você achou que uma classe definida com astruct
palavra - chave não pode ter funções-membro ou construtor?joe()
deve ser definida com aclass
palavra - chave? Toda classe com pelo menos 4int
membros deve ser definida com astruct
palavra - chave?struct
, agregados com métodos são definidos comclass
". Muito aborrecimento.eles são a mesma coisa com padrões diferentes (privado por padrão para
class
e público por padrão parastruct
), 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.
fonte
Estruturas por padrão têm acesso público e classes por padrão têm acesso privado.
Pessoalmente, uso estruturas para objetos de transferência de dados ou como objetos de valor. Quando usado como tal, declaro todos os membros como const para evitar modificações por outro código.
fonte
Ambos
struct
eclass
são as mesmas sob o capô embora com diferentes padrões como a visibilidade,struct
o padrão é público eclass
padrão é privado. Você pode alterar um para o outro com o uso apropriado deprivate
epublic
. 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, enquantoclass
não é. Isso significa que é possível usar astruct
em um arquivo de inclusão que pode estar#include
em C ++ ou C, desde questruct
seja um estilo C simplesstruct
e tudo o mais no arquivo de inclusão seja compatível com C, ou seja, nenhuma palavra-chave específica em C ++, comoprivate
,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 Cstruct
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 Cstruct
.fonte
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.
Por exemplo, estou retornando um aluno struct nos métodos get ... () por aqui - aproveite.
fonte
Eu uso
struct
quando eu definofunctors
ePOD
. Caso contrário, eu usoclass
.fonte
std::binary_function<>
não é apenas obsoleta, o c ++ 17 até a remove.Eu uso estruturas quando preciso criar um tipo ou função de POD.
fonte
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.
fonte
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.
fonte
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).
:(
fonte
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
fonte
struct
já não seria bastante explícito de que os membros da classe serão, por padrão, públicos?