Aqui está o que eu quero dizer:
class MyClass {
int arr1[100];
int arr2[100];
int len = 100;
void add(int* x1, int* x2, int size) {
for (int i = 0; i < size; i++) {
x1[i] += x2[i];
}
}
};
int main() {
MyClass myInstance;
// Fill the arrays...
myInstance.add(myInstance.arr1, myInstance.arr2, myInstance.len);
}
add
já pode acessar todas as variáveis de que precisa, já que é um método de classe, então é uma má idéia? Existem razões pelas quais devo ou não fazer isso?
object-oriented
c++
class-design
methods
encapsulation
homem de papel
fonte
fonte
add
método sem argumento que opera diretamente em seus internos? Só por que?add
método que aceita argumentos, mas não existe como parte de uma classe. Apenas uma função pura para adicionar duas matrizes.Respostas:
Pode haver coisas com a classe que eu faria diferente, mas para responder à pergunta direta, minha resposta seria
sim, é uma má ideia
Minha principal razão para isso é que você não tem controle sobre o que é passado para a
add
função. Claro que você espera que seja uma das matrizes de membros, mas o que acontece se alguém passar em uma matriz diferente que tenha um tamanho menor que 100 ou se você tiver um comprimento maior que 100?O que acontece é que você criou a possibilidade de saturação de buffer. E isso é uma coisa ruim por toda parte.
Para responder a algumas perguntas mais óbvias (para mim):
Você está misturando matrizes de estilo C com C ++. Não sou um guru de C ++, mas sei que o C ++ tem maneiras melhores (mais seguras) de lidar com matrizes
Se a classe já possui as variáveis de membro, por que você precisa passá-las? Esta é mais uma questão arquitetônica.
Outras pessoas com mais experiência em C ++ (eu parei de usá-lo há 10 ou 15 anos) podem ter maneiras mais eloquentes de explicar os problemas e provavelmente também apresentarão mais problemas.
fonte
vector<int>
seria mais adequado; comprimento seria então inútil. Como alternativaconst int len
, como a matriz de comprimento variável não faz parte do padrão C ++ (embora alguns compiladores a suportem, porque é um recurso opcional em C).std::array
que não decaia ao passar para parâmetros, tem uma maneira mais conveniente de obter seu tamanho, é copiável e tem acesso à verificação de limites opcional, sem sobrecarga Matrizes de estilo C.Chamar um método de classe com algumas variáveis de classe não é necessariamente ruim. Mas fazer isso de fora da classe é uma péssima idéia e sugere uma falha fundamental no seu projeto de OO, ou seja, a ausência de encapsulamento adequado :
len
é o comprimento da matriz e usá-lo de forma consistente. Isso vai contra o princípio do mínimo conhecimento . Essa dependência dos detalhes internos da classe é extremamente suscetível a erros e arriscada.len
para uma mais modernastd::vector<int>
), pois exigiria que você também alterasse todo o código usando sua classe.MyClass
objetos, corrompendo algumas variáveis públicas sem respeitar as regras (os chamados invariantes de classe )Você deve refatorar seu código e:
private
ouprotected
, a menos que haja uma boa razão para não fazê-lo.object.action(additional parameters for the action)
:).fonte
Quando a intenção deste design é que você deseja reutilizar esse método para dados que não provêm dessa instância de classe, você pode declará-lo como um
static
método .Um método estático não pertence a nenhuma instância particular de uma classe. É um método da própria classe. Como os métodos estáticos não são executados no contexto de nenhuma instância específica da classe, eles só podem acessar variáveis de membro que também são declaradas como estáticas. Considerando que seu método
add
não se refere a nenhuma das variáveis-membro declaradasMyClass
, é um bom candidato para ser declarado como estático.No entanto, os problemas de segurança mencionados pelas outras respostas são válidos: Você não está verificando se as duas matrizes são pelo menos
len
longas. Se você deseja escrever C ++ moderno e robusto, evite usar matrizes. Use a classestd::vector
sempre que possível. Ao contrário de matrizes regulares, os vetores conhecem seu próprio tamanho. Portanto, você não precisa acompanhar o tamanho deles. A maioria (e não todos!) De seus métodos também faz verificação automática de limites, o que garante que você receba uma exceção ao ler ou escrever além do final. O acesso regular à matriz não faz a verificação vinculada, o que resulta em uma falha padrão na melhor das hipóteses e pode causar uma vulnerabilidade de estouro de buffer explorável na pior das hipóteses .fonte
Um método em uma classe manipula idealmente dados encapsulados dentro da classe. No seu exemplo, não há razão para o método add ter parâmetros, basta usar as propriedades da classe.
fonte
Passar (parte de) um objeto para uma função membro é bom. Ao implementar suas funções, você sempre deve estar ciente de um possível alias e das conseqüências disso.
Obviamente, o contrato pode deixar alguns tipos de alias indefinidos, mesmo que o idioma o suporte.
Exemplos proeminentes:
A atribuição de movimentação automática, por outro lado, embora não deva explodir na sua cara, não precisa ser um não-op.
v.push_back(v[2]);
.std::copy()
assume que o destino não começa dentro da fonte.Mas seu exemplo tem problemas diferentes:
this
. Ele age como uma função de utilidade gratuita, que está simplesmente no lugar errado.Em resumo: Sim, este exemplo é ruim. Mas não porque a função membro é passada para objetos membro.
fonte
Fazer isso especificamente é uma má ideia por vários bons motivos, mas não tenho certeza de que todos sejam parte integrante da sua pergunta:
vector<int>
tornaria sua vida mais fácil.fonte
Esta é uma abordagem clássica "C com classes" para C ++. Na realidade, não é isso que qualquer programador C ++ experiente escreveria. Por um lado, o uso de matrizes C brutas é praticamente universalmente desencorajado, a menos que você esteja implementando uma biblioteca de contêineres.
Algo assim seria mais apropriado:
fonte