Функції члена порівняно з не членами для математичних операторів


12

Я пишу бібліотеку лінійної алгебри (короткий розповідь, це шкільне завдання), яка включає матриці, вектори тощо. У процесі створення цієї бібліотеки я збираюся створювати функції, які виконують математичні операції на об'єктах. Наприклад, перенести матрицю, інвертувати матрицю, нормалізувати вектор тощо.

Мені було цікаво, що є "найкращою практикою" для такого роду функцій ... Тобто, чи варто робити цю функцію членом чи не членом? (Для наочності / використання бібліотеки)

Приклад:

//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);

Чи існує якийсь стандарт щодо таких операцій? Або, принаймні, є загальний спосіб, як це роблять люди? Я схиляюся до першого варіанту, але хотів би знати, чи рекомендується це.

Відповіді:


7

Це лише питання стилю та смаку. Я бачив і різні бібліотеки лінійних алгебр

  • написані в стилі OOP з використанням функцій членів

  • написані в стилі, що не є OOP, використовуючи лише вільні функції

  • надання API з обома

і всі вони працювали. Принаймні, ваш API повинен бути послідовним, тому виберіть свій вибір і переконайтеся, що ви не змішуєте ці стилі довільно.


8

Уникайте членських внесків: Де можливо, віддайте перевагу функціям, які не належать до членів.

Функції, що не належать до друзів, покращують інкапсуляцію, зводячи до мінімуму залежність: Тіло функції не може залежати від непублічних членів класу (див. Пункт 11). Вони також розбивають монолітні класи, щоб звільнити роздільну функціональність, ще більше зменшуючи зв'язок (див. Пункт 33). Вони покращують універсальність, тому що важко писати шаблони, які не знають, чи є операція членом для даного типу [...]

Трава Саттер


1
Нарешті хороша відповідь: Пізно, але не пізно. ;-) Інша довідка: GotW # 84: Моноліти "Unstrung"
дедуплікатор

1

Функції як членів, так і не членів мають реальні переваги, крім простого смаку. Наприклад, базовий масив (и), що використовується для реалізації matrixкласу, ймовірно, буде private, тому вам доведеться використовувати, friendякщо ви не використовуєте функції-учасники. У цьому відношенні дизайн ОО може бути кращим.

Однак майте на увазі, що час від часу комп'ютерним науковцям доводиться реалізовувати складні математичні формули, не знаючи завжди, що ти насправді робиш. Коли мені доведеться це зробити, я віддаю перевагу функціям, що не належать до членів, оскільки "візуальний" результат буде ближчим до початкової математичної формули (оскільки математичні формули зазвичай використовують функціональний стиль).

Зрештою, відповідь така ж, як у дока Брауна: це питання смаку. Коротше кажучи, ви можете розглянути можливість написання бібліотеки у стилі OO з функціями-членами (простіше писати, ні friend), а потім записати функції, які не належать до членів, виконувати ті самі завдання, які просто направлять свої аргументи членам. Це дозволяє бути послідовним і дозволяти користувачеві обирати те, що він вважає найкращим.


0

Якщо ви зануритесь глибше в свою проблему, зрозуміло, що в якийсь момент ви будете використовувати власні структури даних, які представляють певні математичні сутності. Наприклад, ви можете представити матрицю моїх засобів n-мірного масиву. Щоб детальніше розповісти про свій приклад,

// C way
typedef struct {
    int data[MAX_LEN][MAX_LEN];
} MATRIX;

MATRIX B = transpose(A);

// C++ way
class Matrix; // Forward Declaration
class Matrix {
    int data[MAX_LEN][MAX_LEN];
    public:
        Matrix transpose();
};

Matrix B = A.transpose();

(Приклад C ++ спрощений. Ви можете використовувати шаблони тощо).

Слід враховувати простоту використання користувацьких структур даних в обох випадках. C ++ (або будь-який орієнтований на об'єкт) як мова є більш потужним сам по собі, і це поширюється на споживача бібліотеки настільки, наскільки це приносить користь реалізатору. У минулому я використовував лише бібліотеки C, і ці користувальницькі структури даних, здається, отримують всюди за один раз! Тоді як сумісність легше досягти з останніми (можливо, використовуючи спеціальні конструктори?)

Щоб завершити це, якщо ви використовуєте C ++, то однозначно рекомендується об'єктно-орієнтований підхід.


5
Вибачте, у ваших міркуваннях дуже мало твердого факту. Немає різниці у простоті використання між вашими двома transposeприкладами. Основна причина C ++, тобто простіша, полягає в тому, що семантика копіювання та призначення фактично працює. A = Bможе компілювати в C, але, ймовірно, робить неправильну річ.
MSalters

+1 для семантики копіювання Точка, яку я намагався зіткнути, - це використання об'єктів (інкапсуляції над "уявленнями") в / с, використовуючи слабко пов'язаний набір структур та пов'язані з ними функції.
dotbugfix
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.