Alguém pode explicar como esta inicialização dos campos é melhor do que isso:
é melhor do que isso:
E qual é o objetivo, afinal?
No primeiro caso você tem inicialização, e no segundo caso - as operações são realizadas para campos inicializados padrão. Portanto, tudo depende do compilador, ou não faz diferença, ou uma carga de merda de ações extras em tempo de execução. A segunda variante é considerada má forma.
O = operador, como deveria, retorna valor r (5<(val=7) funciona), mas apenas com a semântica de transporte, não há uma aqui, e foi pedida, infelizmente, por isso também não há construtor de transporte.
viram, possivelmente na SB, uma chamada de construtor como esta:
como este código seria diferente:
Descompactei, não vejo nenhuma diferença, então seja um pouco mais específico - o que ou por que podemos usar uma chamada forçada do construtor para objetos a1 e a2?
qual é a "conveniência" da primeira opção?
A primeira opção é chamada - Inicialização de valor, a segunda - Inicialização por padrão. Há sutilezas e diferenças dependendo do tipo de objeto (se é um agregado ou tem um construtor padrão, ...). Por exemplo, o resultado aqui será absolutamente diferente ao usar parênteses e sem eles:
#include <iostream>
usingnamespace std;
struct S {
int i;
int q;
int f;
};
struct Q : S {
Q():S() {}
//Q() {}
};
int main() {
Q s;
cout << s.i << s.q << s.f << endl;
}
Initialization of a variable provides its initial value at the time of construction. The initial value may be provided in the initializer section of a declarator or a new expression. It also takes place during function calls: function parameters and the function return values are also initialized. For each declarator, the initializer may be one...
Ainda não é necessário, mas vou guardá-lo para saber onde ler a fonte.
Obrigado a todos!
Vladimir Simakov: A segunda opção é considerada má forma.
Haverá o mesmo problema que eu encontrei - duplicação de código para inicialização de campos, quando for necessário escrever mais de um construtor na classe
se você usar a variante 2, você pode colocar o código duplicado em um método separado e chamar este método após as ações necessárias em cada construtor (eu tenho inicialização de classe por estrutura e variante 2 pelo nome do arquivo onde os dados desta estrutura são escritos (backup save))
Escrever esse código de repetição é ruim... não é interessante, mas o problema é que, se eu acrescentar um novo campo à classe, tenho que lembrar de inicializar este campo tantas vezes quanto os construtores - o fato, que não é conveniente, mas o fato, que você pode esquecer de fazê-lo N-vezes, é um problema, imho
Ainda não é necessário, mas vou guardá-lo, para saber onde ler a fonte original.
Obrigado a todos vocês!
Haverá o mesmo problema que eu encontrei - duplicação de código para inicialização de campos, quando for necessário escrever mais de um construtor na classe
se você usar a variante 2, você pode colocar o código duplicado em um método separado e chamar este método após as ações necessárias em cada construtor (eu tenho inicialização de classe por estrutura e variante 2 pelo nome do arquivo onde os dados desta estrutura são escritos (backup save))
Escrever esse código de repetição é ruim... não é interessante, mas o problema é que, se eu acrescentar um novo campo à classe, tenho que lembrar de inicializar este campo tantas vezes quanto os construtores - o fato, que não é conveniente, mas o fato, que você pode esquecer de fazê-lo N-vezes, é um problema, imho
Uma macro que também pode ser paramétrica. Esquecer (eu mesmo sofro com isso), também trata com esta))))
haverá o mesmo problema que encontrei - duplicação do código de inicialização de campo quando houver necessidade de escrever mais de um construtor na classe
Se você usar a variante 2, você pode colocar o código duplicado em um método separado e chamar este método após todas as ações necessárias em cada construtor (eu tenho inicialização de classe por estrutura e variante 2 pelo nome de um arquivo onde os dados desta estrutura são escritos (backup save))
Escrever esse código de repetição é ruim... Não é interessante, mas o problema é que, se eu acrescentar um novo campo à classe, terei que lembrar de inicializar este campo tantas vezes quanto há construtores - o fato, que não é conveniente, mas o fato, que você pode esquecer de fazê-lo N-times, é um problema, imho
Vamos lá, tudo pode ser resolvido:
class Q {
void ctr_base(T t, S s) {//make init tasks
}
public:
Q(T t, S s, int i) {
// make base init
ctr_base(t, s);
// make additional tasks
...
}
Q(T t, S s, strint str) {
// make base init
ctr_base(t, s);
// make additional tasks
...
}
};
Não sou contra construtores padrão (ou inicialização padrão), mas se seu construtor deixa o objeto (bem, se não for um agregado idiota) em estado indefinido e depois você o inicializa através de algumas muletas, então você está fazendo tudo errado.
ZS: a propósito, você pode delegar o construtor nos profissionais, faltando, é claro
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};
um pouco à minha frente, acabei de sentar-me no meu PC.
@Vladimir Simakov aconselha a inicializar campos de classe usando uma macro, não esquecer de inicializar corretamente, bem, sim - bom truque, mas o código vai ler como uma chamada para um método que inicializa campos, difícil de assumir que este é um bom tom...
Seu exemplo também não é o mais refinado, mas resolve o problema exatamente da forma como o fiz agora - um método de inicialização separado \.
imho, é uma questão de propósito - a forma correta de escrever uma classe base com todos os campos necessários, herdar dela, proteger o construtor e inicializar a classe base dos herdeiros e, assim, proteger do "esquecimento" - não há construtor padrão, certo? - assim, pelo menos você pode olhar para a mikrosoft se você procurar no Google "construtor protegido" - haverá um artigo
Meu problema é um pouco diferente, eu deixei a herança de propósito, para salvar o estado dos campos de classe em um arquivo, eu tenho 2 campos de 2 classes, e seu estado também é salvo no mesmo arquivo chamando os métodos apropriados. Tentei salvar tudo quando herdei de uma classe base, ficou muito confuso, reescrevi sem herança, tudo se tornou "transparente" agora.
Um pouco à minha frente, acabei de sentar-me no PC.
@Vladimir Simakov aconselha a inicializar campos de classe usando uma macro, para não esquecer de inicializar corretamente, bem, sim, isso é um bom truque, mas o código vai ler como chamar um método que inicializa campos, difícil de assumir que esse é um bom tom...
Seu exemplo também não é o mais refinado, mas resolve o problema exatamente da forma como o fiz agora - um método de inicialização separado \.
imho, é uma questão de propósito - a maneira correta de escrever uma classe base com todos os campos necessários, herdar dela, proteger o construtor e inicializar a classe base dos herdeiros e, assim, proteger do "esquecimento" - não há construtor padrão, certo? - assim, pelo menos você pode olhar para a mikrosoft se você procurar no Google "construtor protegido" - haverá um artigo
Meu problema é um pouco diferente, deixei a herança de propósito, para salvar o estado dos campos de classe em um arquivo, tenho 2 campos de 2 classes e seu estado também é salvo no mesmo arquivo, chamando os métodos apropriados. Tentei salvar tudo quando o herdei de uma classe base, ficou muito complicado; reescrevi-o sem herança, tudo se tornou "transparente" agora.
foi exatamente disso que me afastei, e no início eu fiz
com esta abordagem - herdar de uma classe base, "onde tudo está" - tudo funciona, mas até que queremos tentar fazer vários campos de classe, e então queremos adicionar vários campos em cada classe de campo e pregar tudo com uma matriz dinâmica de classes
e então conseguiremos que não possamos implementar o próprio método Save(int hndl) em uma classe base - este método será na verdade uma interface, que, como discutido acima, não será de forma alguma necessária - você pode escrevê-lo sem interfaces
normalmente maximizo meus esforços em flexibilidade de código - mínimo de confusão - o resultado é um novo problema resolvido, que minha terminologia possa ser perdoada))))
o problema será, ao implementar o salvamento em arquivo, você precisa trabalhar o cabeçalho do arquivo, que deve descrever a quantidade total de diferentes tipos de entradas e então você não precisa perder a lógica / ordem de salvamento de dados, a fim de ler tudo corretamente.... e o final será se você mudar até mesmo um campo em uma classe
imho, a laboriosidade dessa herança "fácil" de uma classe base - se resume ao desenvolvimento e manutenção de um pequeno banco de dados, monitoramento constante das mudanças em qualquer classe
Alguém pode explicar como esta inicialização dos campos é melhor do que isso:
é melhor do que isso:
E qual é o objetivo, afinal?
const podem ser inicializados.
Alguém pode explicar como esta inicialização dos campos é melhor do que isso:
é melhor do que isso:
E qual é o objetivo, afinal?
a questão é puramente teórica:
viram, possivelmente na SB, uma chamada de construtor como esta:
como este código seria diferente:
Descompactei, não vejo nenhuma diferença, então seja um pouco mais específico - o que ou por que podemos usar uma chamada forçada do construtor para objetos a1 e a2?
qual é a "conveniência" da primeira opção?
A primeira opção é chamada - Inicialização de valor, a segunda - Inicialização por padrão. Há sutilezas e diferenças dependendo do tipo de objeto (se é um agregado ou tem um construtor padrão, ...). Por exemplo, o resultado aqui será absolutamente diferente ao usar parênteses e sem eles:
Se você quer entender a teoria até seus ouvidos, vá aqui https://en.cppreference.com/w/cpp/language/initialization
ZS: não é tudo relevante para o mcl, mas como um entendimento do modelo de referência.
Se você quer chegar até seus ouvidos em teoria, vá aqui https://en.cppreference.com/w/cpp/language/initialization
Ainda não é necessário, mas vou guardá-lo para saber onde ler a fonte.
Obrigado a todos!
A segunda opção é considerada má forma.
Haverá o mesmo problema que eu encontrei - duplicação de código para inicialização de campos, quando for necessário escrever mais de um construtor na classe
se você usar a variante 2, você pode colocar o código duplicado em um método separado e chamar este método após as ações necessárias em cada construtor (eu tenho inicialização de classe por estrutura e variante 2 pelo nome do arquivo onde os dados desta estrutura são escritos (backup save))
Escrever esse código de repetição é ruim... não é interessante, mas o problema é que, se eu acrescentar um novo campo à classe, tenho que lembrar de inicializar este campo tantas vezes quanto os construtores - o fato, que não é conveniente, mas o fato, que você pode esquecer de fazê-lo N-vezes, é um problema, imho
Ainda não é necessário, mas vou guardá-lo, para saber onde ler a fonte original.
Obrigado a todos vocês!
Haverá o mesmo problema que eu encontrei - duplicação de código para inicialização de campos, quando for necessário escrever mais de um construtor na classe
se você usar a variante 2, você pode colocar o código duplicado em um método separado e chamar este método após as ações necessárias em cada construtor (eu tenho inicialização de classe por estrutura e variante 2 pelo nome do arquivo onde os dados desta estrutura são escritos (backup save))
Escrever esse código de repetição é ruim... não é interessante, mas o problema é que, se eu acrescentar um novo campo à classe, tenho que lembrar de inicializar este campo tantas vezes quanto os construtores - o fato, que não é conveniente, mas o fato, que você pode esquecer de fazê-lo N-vezes, é um problema, imho
Uma macro que também pode ser paramétrica. Esquecer (eu mesmo sofro com isso), também trata com esta))))
haverá o mesmo problema que encontrei - duplicação do código de inicialização de campo quando houver necessidade de escrever mais de um construtor na classe
Se você usar a variante 2, você pode colocar o código duplicado em um método separado e chamar este método após todas as ações necessárias em cada construtor (eu tenho inicialização de classe por estrutura e variante 2 pelo nome de um arquivo onde os dados desta estrutura são escritos (backup save))
Escrever esse código de repetição é ruim... Não é interessante, mas o problema é que, se eu acrescentar um novo campo à classe, terei que lembrar de inicializar este campo tantas vezes quanto há construtores - o fato, que não é conveniente, mas o fato, que você pode esquecer de fazê-lo N-times, é um problema, imho
Vamos lá, tudo pode ser resolvido:
Não sou contra construtores padrão (ou inicialização padrão), mas se seu construtor deixa o objeto (bem, se não for um agregado idiota) em estado indefinido e depois você o inicializa através de algumas muletas, então você está fazendo tudo errado.
ZS: a propósito, você pode delegar o construtor nos profissionais, faltando, é claro
Vá lá, é solvível:
um pouco à minha frente, acabei de sentar-me no meu PC.
@Vladimir Simakov aconselha a inicializar campos de classe usando uma macro, não esquecer de inicializar corretamente, bem, sim - bom truque, mas o código vai ler como uma chamada para um método que inicializa campos, difícil de assumir que este é um bom tom...
Seu exemplo também não é o mais refinado, mas resolve o problema exatamente da forma como o fiz agora - um método de inicialização separado \.
imho, é uma questão de propósito - a forma correta de escrever uma classe base com todos os campos necessários, herdar dela, proteger o construtor e inicializar a classe base dos herdeiros e, assim, proteger do "esquecimento" - não há construtor padrão, certo? - assim, pelo menos você pode olhar para a mikrosoft se você procurar no Google "construtor protegido" - haverá um artigo
Meu problema é um pouco diferente, eu deixei a herança de propósito, para salvar o estado dos campos de classe em um arquivo, eu tenho 2 campos de 2 classes, e seu estado também é salvo no mesmo arquivo chamando os métodos apropriados. Tentei salvar tudo quando herdei de uma classe base, ficou muito confuso, reescrevi sem herança, tudo se tornou "transparente" agora.
Um pouco à minha frente, acabei de sentar-me no PC.
@Vladimir Simakov aconselha a inicializar campos de classe usando uma macro, para não esquecer de inicializar corretamente, bem, sim, isso é um bom truque, mas o código vai ler como chamar um método que inicializa campos, difícil de assumir que esse é um bom tom...
Seu exemplo também não é o mais refinado, mas resolve o problema exatamente da forma como o fiz agora - um método de inicialização separado \.
imho, é uma questão de propósito - a maneira correta de escrever uma classe base com todos os campos necessários, herdar dela, proteger o construtor e inicializar a classe base dos herdeiros e, assim, proteger do "esquecimento" - não há construtor padrão, certo? - assim, pelo menos você pode olhar para a mikrosoft se você procurar no Google "construtor protegido" - haverá um artigo
Meu problema é um pouco diferente, deixei a herança de propósito, para salvar o estado dos campos de classe em um arquivo, tenho 2 campos de 2 classes e seu estado também é salvo no mesmo arquivo, chamando os métodos apropriados. Tentei salvar tudo quando o herdei de uma classe base, ficou muito complicado; reescrevi-o sem herança, tudo se tornou "transparente" agora.
O que há de tão confuso nisso?
O que há de tão confuso nisso?
foi exatamente disso que me afastei, e no início eu fiz
com esta abordagem - herdar de uma classe base, "onde tudo está" - tudo funciona, mas até que queremos tentar fazer vários campos de classe, e então queremos adicionar vários campos em cada classe de campo e pregar tudo com uma matriz dinâmica de classes
e então conseguiremos que não possamos implementar o próprio método Save(int hndl) em uma classe base - este método será na verdade uma interface, que, como discutido acima, não será de forma alguma necessária - você pode escrevê-lo sem interfaces
normalmente maximizo meus esforços em flexibilidade de código - mínimo de confusão - o resultado é um novo problema resolvido, que minha terminologia possa ser perdoada))))
o problema será, ao implementar o salvamento em arquivo, você precisa trabalhar o cabeçalho do arquivo, que deve descrever a quantidade total de diferentes tipos de entradas e então você não precisa perder a lógica / ordem de salvamento de dados, a fim de ler tudo corretamente.... e o final será se você mudar até mesmo um campo em uma classe
imho, a laboriosidade dessa herança "fácil" de uma classe base - se resume ao desenvolvimento e manutenção de um pequeno banco de dados, monitoramento constante das mudanças em qualquer classe