Estou escrevendo uma biblioteca de álgebra linear (para encurtar a história, é uma tarefa da escola) que envolve matrizes, vetores etc. No processo de criação dessa biblioteca, vou criar funções que executam operações matemáticas em objetos. Por exemplo, transponha matriz, matriz invertida, normalize vetor etc.
Fiquei curioso para saber qual é a "melhor prática" para esse tipo de função ... Ou seja, devo fazer da função uma função membro ou não membro? (Para maior clareza / uso da biblioteca)
Exemplo:
//Member function way:
B = A.transpose();
C = A.inverse();
//Non-member function way:
B = linalg::transpose(A); //Non-member transpose function in linear algebra namespace
C = linalg::inverse(A);
Existe algum padrão em relação a esse tipo de operação? Ou, pelo menos, existe uma maneira comum de as pessoas fazerem isso? Estou inclinado para a primeira opção, mas gostaria de saber se isso é recomendado.
As funções de membro e de não membro têm vantagens reais além do mero gosto. Por exemplo, o (s) array (s) subjacente (s) usado (s) para implementar uma
matrix
classe provavelmente seráprivate
, portanto, você precisará usá-friend
lo, a menos que use funções-membro. Nesse aspecto, um design de OO pode ser melhor.No entanto, lembre-se de que, de tempos em tempos, os cientistas da computação precisam implementar uma fórmula matemática complexa sem sempre saber o que realmente faz. Quando preciso fazer isso, prefiro funções que não sejam membros, pois o resultado "visual" estará mais próximo da fórmula matemática original (uma vez que a fórmula matemática geralmente usa um estilo funcional).
No final, a resposta é a mesma do doutor Brown: é uma questão de gosto. Em resumo, você pode considerar escrever uma biblioteca no estilo OO com funções-membro (mais fácil de escrever, não
friend
) e depois escrever funções não-membros para executar as mesmas tarefas que simplesmente encaminham seus argumentos para os membros. Ele permite que você seja consistente e permita que o usuário escolha o que acha melhor.fonte
Se você se aprofundar na declaração do problema, é claro que em algum momento você usará estruturas de dados personalizadas que representam certas entidades matemáticas. Por exemplo, você pode representar uma matriz meus meios de uma matriz n-dimensional. Para elaborar seu exemplo,
(O exemplo de C ++ é simplificado, você pode usar modelos e coisas assim.)
O ponto a considerar é a facilidade de usar estruturas de dados personalizadas nos dois casos. O C ++ (ou qualquer outro objeto orientado) como uma linguagem é mais poderoso por si só, e isso se estende ao consumidor da biblioteca tanto quanto beneficia o implementador. Eu usei bibliotecas apenas C no passado e essas estruturas de dados personalizadas parecem chegar a todo o lugar em pouco tempo! Considerando que a interoperabilidade é mais fácil de alcançar com o último (usando construtores especiais, talvez?)
Para encerrar, se você estiver usando C ++, uma abordagem orientada a objetos é definitivamente recomendada.
fonte
transpose
exemplos. O principal motivo pelo qual o C ++ é mais fácil, é porque a semântica de cópia e atribuição realmente funciona.A = B
pode compilar em C, mas provavelmente faz a coisa errada.