2016-03-22 5 views
6

mam klasy C++ z dwóch elementów danych, na przykładC++ const zainicjowania wielu elementów danych z jedną funkcję inicjatora

class mytest() { 
    public: 
    mytest(): 
     a_(initA()), 
     b_(initB()) 
    {}; 
    virtual ~mytest() {}; 

    private: 
    double initA() { 
     // some complex computation 
    } 
    double initB() { 
     // some other complex computation 
    } 

    private: 
     const double a_; 
     const double b_; 
} 

Niestety jednak initA i initB nie może być oddzielony jak naszkicowane powyżej. Zarówno a_ i b_ może być inicjowane przez jeden duży złożonych obliczeń, gdy wartość b_ zależy wynik pośredni do obliczenia a_, np

void mytest::init() const { 
    const double a = 1.0 + 1.0; // some complex computation 
    const double b = 2*(a + 1.0); // another complex computation 
    a = 2 * a; // even more complex, wow 
    // Now, a and b contain the data from which a_ and b_ should be initialized. 
} 

ja chce zachować a_ i b_ oddzielne (i const) zmiennych (i nie umieszczaj ich w std::tuple lub podobnych). Jednak nie wiem, czy możliwe jest zainicjowanie a_ i b_ niezależnie od pojedynczej funkcji.

Jakieś wskazówki?

+0

dobrze najpierw trzeba initilize te const członków w liście inicjatora w konstruktorze, a nie w jakiś funkcja członkowska – Guiroux

+0

'a_' i' b_' powinny być inicjowane przez konstruktor: 'mytest(): a_ (valueA), b_ (valueB) {}' gdzie 'valueX' może być wartością bezpośrednią, parametrem z konstruktora lub funkcja zwracająca obliczoną wartość. Również posiadanie funkcji o nazwie 'init' jest dziwne: podczas tworzenia obiektu wywoływany jest konstruktor, a po inicjalizacji tego obiektu. To tak jakby mieć funkcję o nazwie 'deinit', która powinna być wywołana przed destruktorem ... bez sensu – Garf365

+0

Po prostu zainicjuj je na liście inicjalizacji. Jeśli nie możesz, pokaż jakiś odpowiedni kod. – juanchopanza

Odpowiedz

4

Możesz dodać dodatkową funkcję pośrednią/struct zainicjować swoją klasę

z delegowania konstruktora:

struct MytestHelper 
{ 
    double a; 
    double b; 
}; 

MytestHelper someComplexComputation(); // feed `a` and `b` 

class mytest() { 
    public: 
    mytest() : mytest(someComplexComputation()) {} 
    virtual ~mytest() {}; 

    private: 
    mytest(const MytestHelper& h) : a_(h.a), b_(h.b) {} 

    private: 
     const double a_; 
     const double b_; 
}; 
+2

Brilliant! Dodaj kolejny przykład do (długiej) listy "Wszystkie problemy w informatyce można rozwiązać, dodając kolejną warstwę pośrednią (z wyjątkiem zbyt wielu warstw pośrednich)." –

+0

Nie będę mógł skorzystać z pierwszej sugestii, ponieważ 'b_' zależy od wyniku _intermediate_' someComplexComputation() '. Delegowanie konstruktorów zrobi jednak. –

+0

Czy mogę zasugerować usunięcie pierwszej sugestii? PO wyjaśnił, że rozumie to podejście, ale że obliczanie tych dwóch zmiennych jest ściśle powiązane i nie można go podzielić na dwie takie funkcje. –

2

Co zasugeruję może wydawać się oczywiste, ale absolutnie nie ma potrzeby używania const dla zmiennych członkowskich. Jeśli chcesz, aby twój typ był niezmienny, po prostu nie podawaj metod ustawiania i obliczaj wartości swoich członków w konstruktorze.

class mytest() { 
    public: 
    mytest() { 
     a_ = 1.0 + 1.0; // some complex computation 
     b_ = 2.0 *(a + 1.0); // another complex computation 
     a_ = 2.0 * a_; // even more complex, wow  
    }; 

    // Make your methods const to prevent modification of the members 
    void testMethod() const { 
     // a_ = 20.0; // Will result in an error! 
     std::cout << "sum = " << a_ + b_ << '\n'; // perfectly fine 
    } 

    virtual ~mytest() {}; 

    private: 
     double a_; 
     double b_; 
}; 

Jest to o wiele prostsze i osiąga to, co chcesz.

+0

Down-voter, wyjaśnij proszę –

+2

nie powinieneś pozwalać ludziom na modyfikowanie rzeczy, które nie powinny być modyfikowalne, myślę, że nawet ty sam (nie jestem odległą myślą :-P) – Guiroux

+2

Zgadzam się. Członkowie "const" mają o wiele więcej kłopotów, niż są tego warte. Zapobiegają one przenoszeniu przenoszenia i przynoszą niewielkie korzyści. – Angew

-1

Zawsze możesz odrzucić konsternację, ale naprawdę przemyślałbym twój projekt, a nie robił to.

// some pointer 
double *ptr; 
// give it the value of '_a' 
ptr = (double*)(&_a); 
// change the value now 
*ptr = 5.34; 

Również w kodzie

const double a = 1.0 + 1.0; 

Powinny być

double a = 1.0 + 1.0; 

Nie ma potrzeby, aby była ona const.

+0

Powiedziałbym, że 'const double a = 1.0 + 1.0' powinno być' constexpr double a = 1.0 + 1.0' –