C / C ++ Struct vs Classe

108

Depois de terminar minha aula de C ++, pareceu-me que as estruturas / classes são virtualmente idênticas, exceto com algumas pequenas diferenças.

Nunca programei em C antes; mas eu sei que tem structs. Em C, é possível herdar outras estruturas e definir um modificador de público / privado?

Se você pode fazer isso em C normal, por que diabos precisamos de C ++? O que torna as classes diferentes de uma estrutura?


fonte
possível duplicata stackoverflow.com/questions/54585/…
gonzobrains

Respostas:

146

Em C ++ , structs e classes são praticamente os mesmos; a única diferença é que onde os modificadores de acesso (para variáveis ​​de membro, métodos e classes base) em classes são padronizados como privados, os modificadores de acesso em estruturas são padronizados como públicos.

No entanto, em C , uma estrutura é apenas uma coleção agregada de dados (públicos) e não tem outros recursos semelhantes a classes: nenhum método, nenhum construtor, nenhuma classe base etc. Embora C ++ tenha herdado a palavra-chave, ela estendeu a semântica. (É por isso, no entanto, que as coisas são padronizadas para estruturas públicas - uma estrutura escrita como uma estrutura C se comporta como tal.)

Embora seja possível falsificar alguma OOP em C - por exemplo, definir funções que levam um ponteiro para uma estrutura como seu primeiro parâmetro ou, ocasionalmente, coagir estruturas com os mesmos primeiros campos a serem "sub / superclasses" - é sempre uma espécie de aparafusado e não faz realmente parte da linguagem.

Antal Spector-Zabusky
fonte
A partir de OOP. Os caras do .Net em potencial definiram dessa forma ✓ CONSIDERE definir uma estrutura em vez de uma classe se as instâncias do tipo são pequenas e geralmente de curta duração ou são comumente embutidas em outros objetos. X EVITE definir uma estrutura a menos que o tipo tenha todas as seguintes características: 1. Ele logicamente representa um único valor, semelhante aos tipos primitivos (int, double, etc.). 2. Tem um tamanho de instância inferior a 16 bytes. 3. É imutável.
Abhijeet
5
@Abhijeet Essa é a distinção entre estruturas e classes em C #, mas isso é simplesmente irrelevante para C ++, e ainda mais para C. Em C #, classes e estruturas são realmente diferentes; não é assim em C ++, e C só tem structs sem OO.
Antal Spector-Zabusky
não seria melhor ter mantido a mesma semântica C na estrutura C ++? e quando necessário para usar uma "estrutura de forma c ++" basta usar uma classe? Eu nunca tive o benefício de ter uma estrutura "aumentada" em C ++ em comparação com C. Eu gosto de ainda usar a estrutura como foi projetada em C, caso contrário, uso uma classe, com algumas exceções permitidas.
Raffaello
15

Fora as diferenças no acesso padrão (público / privado), não há diferença.

No entanto, algumas lojas que codificam em C e C ++ usarão "classe / estrutura" para indicar o que pode ser usado em C e C ++ (estrutura) e que são apenas C ++ (classe). Em outras palavras, neste estilo todas as estruturas devem funcionar com C e C ++. É por isso que havia uma diferença em primeiro lugar há muito tempo, quando C ++ ainda era conhecido como "C com classes".

Observe que as uniões C funcionam com C ++, mas não o contrário. Por exemplo

union WorksWithCppOnly{
    WorksWithCppOnly():a(0){}
    friend class FloatAccessor;
    int a;
private:
    float b;
};

E da mesma forma

typedef union friend{
    int a;
    float b;
} class;

só funciona em C

Lance Diduck
fonte
9
Usar palavras-chave cpp em seu código C e, em seguida, alegar que não é compatível com cpp é bastante estúpido
Dani
7

Vou adicionar às respostas existentes porque o C ++ moderno agora é uma coisa e as Diretrizes Principais oficiais foram criadas para ajudar com questões como essas.

Esta é uma seção relevante das diretrizes:

C.2: Use classe se a classe tiver um invariante; use struct se os membros de dados puderem variar independentemente

Uma invariante é uma condição lógica para os membros de um objeto que um construtor deve estabelecer para que as funções de membro público assumam. Depois que o invariante é estabelecido (normalmente por um construtor), cada função de membro pode ser chamada para o objeto. Um invariante pode ser declarado informalmente (por exemplo, em um comentário) ou mais formalmente usando Expects.

Se todos os membros de dados podem variar independentemente uns dos outros, nenhum invariante é possível.

Se uma classe tiver dados privados, um usuário não pode inicializar completamente um objeto sem o uso de um construtor. Portanto, o definidor de classe fornecerá um construtor e deve especificar seu significado. Isso efetivamente significa que o definidor precisa definir um invariante.

Execução

Procure structs com todos os dados privados e classes com membros públicos.

Os exemplos de código fornecidos:

struct Pair {  // the members can vary independently
    string name;
    int volume;
};

// but

class Date {
public:
    // validate that {yy, mm, dd} is a valid date and initialize
    Date(int yy, Month mm, char dd);
    // ...
private:
    int y;
    Month m;
    char d;    // day
};

Classs funcionam bem para membros que são, por exemplo, derivados uns dos outros ou inter-relacionados. Eles também podem ajudar na verificação de sanidade na instanciação.Structs funcionam bem para ter "pacotes de dados", onde nada de especial está realmente acontecendo, mas os membros logicamente fazem sentido serem agrupados.

A partir disso, faz sentido que classexistam para suportar encapsulamento e outros conceitos de codificação relacionados, para os quais structos programas simplesmente não são muito úteis.

Dave
fonte
Uma outra consideração é a portabilidade. structs são os mais portáteis. Eles podem ser usados ​​por C ou C ++ ou para frente e para trás. Eles também podem ser descompactados em Python usando o structmódulo, por exemplo. Se seus Prioriza projeto ser compatível com outras linguagens, interfaces ou sistemas, preferem structmais class. Para assuntos estritamente internos do programa, prefira class.
Dave
6

Não é possível definir funções-membro ou derivar estruturas umas das outras em C.

Além disso, C ++ não é apenas C + "derivar estruturas". Modelos, referências, namespaces definidos pelo usuário e sobrecarga de operadores não existem em C.

Johannes Schaub - litb
fonte
Eu sei que os templates, etc não existem em C, mas eu não estava ciente powerdos structs em C. Então, C ++ só usa structs para ser 'retroativamente' compatível com C?
4
Apenas para compatibilidade com versões anteriores? Em uma base prática, provavelmente há algo nisso, mas a distinção pode ser um sinal de intenção: onde eu uso um, structquero dizer um tipo de coisa POD amplamente passivo.
dmckee --- ex-moderador gatinho
@dmckee: Pelo que vale, a maioria dos functores STL (isto é std::less) são definidos como estruturas, não classes.
Billy ONeal
1
C ++ não é totalmente compatível com o C. Você poderia dizer que a palavra-chave struct é uma acomodação para desenvolvedores C. Eu gosto da palavra-chave struct para classes que simplesmente mantêm dados de forma ordenada, mas não fornecem (muita) lógica por si mesmas.
ypnos
@ypnos: Veja meu último comentário. A única diferença entre os dois é que os membros de um são públicos padrão e os outros são privados.
Billy ONeal
3

Mais uma diferença em C ++, quando você herda uma classe de struct sem nenhum especificador de acesso, ela se torna herança pública onde, como no caso da classe, é herança privada.

MarsRover
fonte
1

C ++ usa estruturas principalmente para 1) compatibilidade com versões anteriores com C e 2) tipos de POD. C structs não possuem métodos, herança ou visibilidade.

Chris Hafey
fonte
2
Pelo que vale, a maioria dos functores STL (ou seja std::less) são definidos como estruturas, não classes.
Billy ONeal
3
Observe que as estruturas C ++ têm métodos, herança e visibilidade.
robertwb
c struct pode incluir um ponteiro de função como type (* addr) (params);
Erro de