2012-04-04 4 views
5

mam jakąś klasę Foo i Rejestrator:Jak utworzyć tablicę z elementem odniesienia w C++?

class Logger{/* something goes here */}; 
class Foo{ 
    Foo(Logger& logger); 
    Logger& logger; 
} 

Foo::Foo(Logger& logger) : logger(logger) 
{} 

Teraz chcę utworzyć tablicę obiektów klasy Foo, gdzie wszystkie odniesienia Foo::logger powinien wskazywać na tym samym Logger obiektu. Próbowałem coś podobnego (muszę zarówno stosu i sterty alokacji)

Logger log (/* parameters */); 
Foo objects [3] (log); // On stack 
Foo* pObjects = new Foo [3] (log); // On heap 

Problemem jest to, że obie wersje próbować wywołać konstruktora domyślnego Foo() który nie jest obecny. Ponadto, jak rozumiem, nie jest możliwa zmiana odniesionej zmiennej odniesienia. Zatem tymczasowe wywołanie domyślnego konstruktora i późniejsze zainicjowanie w pętli również nie pomaga.

A więc: Jaki jest właściwy sposób? Czy muszę używać wskaźników do obiektu Logger?

Odpowiedz

2

Do ogólnych zastosowań zwykle tworzę rejestrator Singleton, więc jest tylko jeden i można uzyskać do niego dostęp ze wszystkich komponentów. http://en.wikipedia.org/wiki/Singleton_pattern

Dzięki temu konstruktor Foo jest znacznie prostszy.

class Logger 
{ 
    public: 
     static Logger& getInstance() 
     { 
      static Logger instance; 
      return instance; 
     } 

     public log(const std::string& txt) 
     { 
      //do something 
     } 

    private: 
     Logger() {} 
     Logger(Logger const&);    // Don't Implement. 
     void operator=(Logger const&); // Don't implement 
}; 

i używać go w Foo jak:

Logger::getInstance().log("test"); 

lub

Logger& logger = Logger::getInstance(); 
logger.log("test"); 

(kredyty dla Singleton z @Loki Astari: C++ Singleton design pattern)

+0

Aby być pewnym, że Cię rozumiem: Masz na myśli jakiś statyczny element dla wszystkich obiektów? Jak to zainicjować? Lub oddzielny obiekt/zmienna globalna/...? –

+0

On oznacza klasę singleton dostępną z każdego miejsca w kodzie. Jest to powszechny sposób dla rejestratorów. – giorashc

5

Nie można zainicjować tablicy obiektów przy użyciu innego niż domyślny konstruktora. Jednakże można użyć wektor jak pokazano here (Spójrz na pierwszy post)

A do hałdy można wykonać następujące czynności:

Foo* pObjects[3]; 

for (int i = 0; i < 3; ++i) { 
    pObjects[i] = new Foo(log); 
} 
2

można zainicjować tablicę objecs z niedomyślnymi konstruktor używając C++ 11 nawiasów inicjalizacji:

class Logger{/* something goes here */}; 
class Foo{ 
public: 
    Foo(Logger& logger); 
private: 
    Logger& logger; 
}; 

Foo::Foo(Logger& logger) : logger(logger) 
{} 


EDIT: w C++ 11, można użyć vector robić to, co chcesz:

#include <vector> 
class Logger{/* something goes here */}; 
class Foo{ 
public: 
    Foo(Logger& logger) : logger(logger) {} 
private: 
    Logger& logger; 
}; 

int main() { 
    Logger log; 
    std::vector<Foo>(3, log); 
} 

Należy zauważyć, że rozwiązanie vector nie będzie działać w C++ 03. W C++ 03 ten konstruktor wektorowy wywołuje Foo::operator=. W C++ 11 wywołuje on Foo::Foo(const Foo&).

+0

To działa tylko wtedy, gdy wiem, że liczba elementów a priori, prawda? Nie zawsze dotyczy to mojego problemu. –

+0

To prawda, to jest problem. Ale zdaj sobie sprawę, że musisz znać liczbę elementów * a priori * podczas tworzenia tablic na stosie. –