2012-12-30 9 views
6

Załóżmy, że mam klasę Utility w pliku utility.h:Jaki jest najbezpieczniejszy sposób na zdefiniowanie aliasów nazw krótkich funkcji w C++?

class Utility { 
public: 
    static double longDescriptiveName(double x) { return x + 42; } 
}; 

I wtedy okaże się, że mogę korzystać z funkcji longDescriptiveName(...) dużo. Tak jak nieodpowiedzialny programista C++, że jestem kiedy miałem zbyt dużo kawy, tworzę nowy plik utilitymacros.h i dodać następujące tam:

#define ldn Utility::longDescriptiveName 

Teraz to "utilitymacros.h" w dowolnym *.cpp gdzie używam ldn(...) i My serce napełnia się radością nad tym, jak wiele bardziej wygodnym to jest typ 3 litery vs 28.

Pytanie: Czy jest bezpieczniejsze (bardziej właściwe) sposób to zrobić niż z #define?

Zauważyłem, że muszę dołączyć "utilitymacros.h" po dodaniu nagłówków doładowania, których oczywiście nie lubię, ponieważ jest to oznaka starć (chociaż otrzymane błędy Boost nie są zbyt jasne co do tego, zderzenie jest).

Wyjaśnienie 1: Na czytelności kodu

W przypadku można powiedzieć, że ta negatywnie wpływa na czytelność kodu, zapewniam cię, że nie, bo to mały zestaw funkcji, które są wykorzystywane dużo. Przykładem, który jest powszechnie znany, jest stoi dla stringToInteger. Innym jest pdf dla probabilityDensityFunction itp Więc jeśli chcę wykonać następujące czynności, stoi jest bardziej czytelny moim zdaniem:

int x = stoi(a) + stoi(b) + stoi(c) + stoi(d); 

niż:

int x = Utility::stringToInteger(a) + Utility::stringToInteger(b) 
     + Utility::stringToInteger(c) + Utility::stringToInteger(d); 

czyli

int x = Utility::stringToInteger(a); 
x += Utility::stringToInteger(b); 
x += Utility::stringToInteger(c); 
x += Utility::stringToInteger(d); 

Klasyfikacja 2: Makro edytora

Używam Emacsa jako mojego IDE i klawiatury Kinesis, dzięki czemu wiesz, że używam mnóstwa makr na klawiaturze, niestandardowych skrótów klawiaturowych, a także faktycznie modyfikuję to, co widzę w edytorze, a co faktycznie jest przechowywane w pliku h/cpp . Ale wciąż mam wrażenie, że prostota i czytelność wizualna (jak argumentowano powyżej) użycia skrótu funkcji w kilku wybranych przypadkach jest tak naprawdę wynikiem, którego szukam (jest to z pewnością zależne od stopnia).

+3

Nie sądzę, że to dobry pomysł, ponieważ szkodzi to czytelności kodu. –

+1

Założę się, że 'pdf' był formatem pliku, i * naprawdę * był zdezorientowany. Postaci są bezpłatne i nie oszczędzasz środowiska, nie używając ich. –

+0

Cóż, może krótkie nazwy są czytelne dla CIEBIE, ale dla innych są trudne, nawet (lub szczególnie), gdy są używane wszędzie. W moim starym było wiele 3-znakowych nazw funkcji i był to jeden z wielu powodów, dla których odstąpiłem od tego: kod był nieczytelnym bałaganem. Jasne, nie tylko ze względu na nazwy funkcji i nazw zmiennych, ale także część z nich. – Skalli

Odpowiedz

12

Zamiast makro, można napisać inline funkcję, która przekierowuje połączenie do rzeczywistej funkcji:

inline double ldn(double x) 
{ 
    return Utility::longDescriptiveName(x); 
} 

To z pewnością bezpieczniejsze niż makro.

+2

+1 zdecydowanie funkcje inline są bezpieczniejsze, ponieważ sprawdzanie typu i myślę, że zaleca się, aby używać (styl C++) zamiast #define (styl C i mniej bezpieczne). Na marginesie: w przeciwieństwie do wbudowanych makr nie ma żadnego typu danych, który jest realizowany za pomocą szablonów z wbudowanym! – Abdurahman

+0

@Nawaz, Zakładam, że funkcja inline nie jest częścią klasy 'Utility', poprawne? W takim przypadku, czy zaproponowałbyś wstawienie definicji w tym samym nagłówku, co 'utility.h' lub stworzenie osobnego nagłówka dla nich, jak' utilityhelpers.h'? –

+0

@LexFridman: Tak. Jest poza klasą 'Utility'. Możesz umieścić go w tym samym nagłówku, ale poza klasą. To zależy od Ciebie. – Nawaz

3

Co powiesz na skonfigurowanie snippitu/makra/podobnej rzeczy w edytorze tekstu? W ten sposób wystarczy wpisać ldn lub coś w tym stylu, a kod nie musi przebiegać przez preprocesor, ryzykując, że później trudno będzie znaleźć błędy.

+2

Plus, będzie zrozumiały po tym, jak zostanie wpisany. – delnan

6

Można użyć odniesienie funkcję:

double (&ldn)(double) = Utility::longDescriptiveName; 
+0

Czy nie powinno to być "statyczne podwójne (& ldn) (podwójne) = ..."? – Nawaz

+0

@Nawaz Yeah Dzięki. :) – 0x499602D2

+2

W C++ 11, 'auto && ldn = Utility :: longDescriptiveName;' co jest bardzo idiomatyczne. Jaką przewagę ma "statyczny" w każdym przypadku? – Potatoswatter

2

ja nie wiem, czy to pomoże, ale myślę, że częścią problemu może być użycie zbyt ogólnych nazw (lub nazw klas, w tym przypadku), na przykład Utility.

Jeśli zamiast Utility::stringToInteger, mieliśmy

namespace utility { 
    namespace type_conversion { 
    namespace string { 
     int to_int(const std::string &s); 
    } 
    } 
} 

Następnie funkcja mogła lokalnie być używane tak:

void local_function() 
{ 
    using namespace utility::type_conversion::string; 

    int sum = to_int(a) + to_int(b) + to_int(c) + to_int(d); 
} 

Analogicznie, jeśli stosowane są ćwiczenia/kodowanym i funkcje statyczne (i nie może być tego powodem), mamy coś w rodzaju:

strut utility { 
    struct type_conversion { 
    struct string { 
     static int to_int(const std::string &s); 
    }; 
    }; 
}; 

lokalna funkcja wyglądałaby tak:

void local_function() 
{ 
    typedef utility::type_conversion::string str; 

    int sum = str::to_int(a) + str::to_int(b) 
       + str::to_int(c) + str::to_int(d); 
} 

Zdaję sobie sprawę, że nic ci nie mówię o składni, której już nie znałeś; przypomina to raczej o tym, że sama organizacja i struktura przestrzeni nazw i klas odgrywa ważną rolę w zwiększaniu czytelności kodu (i zapisywalności).

2

Jedną z alternatyw jest zmiana nazwy funkcji i umieszczenie jej w przestrzeni nazw zamiast w klasie, ponieważ i tak jest statyczna. utility.h staje

namespace Utility { 
    // long descriptive comment 
    inline double ldn(double x) { return x + 42; } 
} 

Następnie można umieścić using namespace Utility; w kodzie klienta.

Wiem, że istnieje wiele przewodników po stylach mówiących, że krótkie imiona są złe, ale nie widzę sensu słuchania jakiegoś stylu, a następnie obchodzenia go.

Powiązane problemy