2012-04-04 1 views
5

Ich habe einige Klasse Foo und Logger:Wie erstellt man ein Array mit Referenz-Member in C++?

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

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

Jetzt möchte ich ein Array von Objekten der Klasse Foo erstellen, in dem alle Referenzen Foo::logger auf den gleichen Logger Objekt zeigen sollte. Ich habe versucht, so etwas wie (ich brauche sowohl Stack und Heap-Allokation):

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

Das Problem ist, dass beide Versionen Foo() den Standard-Konstruktor aufzurufen, die nicht vorhanden ist. Ebenso wie ich es verstehe, ist es nicht möglich, die referenzierte Variable einer Referenz zu ändern. Daher hilft auch ein temporärer Aufruf des Standardkonstruktors und eine spätere Initalisierung in einer Schleife nicht.

Also: Was ist der richtige Weg? Muss ich Zeiger auf das Objekt Logger verwenden?

Antwort

2

Für allgemeine Zwecke mache ich normalerweise einen Logger einen Singleton, so dass es nur einen gibt und von allen Komponenten zugegriffen werden kann. http://en.wikipedia.org/wiki/Singleton_pattern

Dies macht auch den Konstruktor von Foo viel einfacher.

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 
}; 

Und es in Foo verwenden wie:

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

oder

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

(Credits für Singleton von @Loki Astari: C++ Singleton design pattern)

+0

Um sicher zu sein, dass ich Sie verstehe: Sie meinen ein statisches Mitglied für alle Objekte? Wie initialisiert man es dann? Oder ein separates Objekt/globale Variable/...? –

+0

Er meint eine Singleton-Klasse, die von überall in Ihrem Code zugänglich ist. Dies ist der übliche Weg für Logger. – giorashc

5

Sie können ein Array von Objekten mit einem nicht standardmäßigen Konstruktor nicht initialisieren. jedoch ein Vektor here wie gezeigt verwenden (bei der ersten Antwort Schauen)

Und für den Heap können Sie folgendes tun:

Foo* pObjects[3]; 

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

Sie eine Reihe von objecs mit der Nicht-Standard-initialisieren Konstruktor der C++ 11 Klammer Initialisierung mit:

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

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


EDIT: In C++ 11, können Sie vector verwenden

#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); 
} 

Beachten Sie, dass die vector Lösung wird nicht funktionieren in C++ 03: zu tun, was Sie wollen. In C++ 03 ruft der Vektorkonstruktor Foo::operator= auf. In C++ 11 ruft es Foo::Foo(const Foo&) auf.

+0

Das funktioniert nur, wenn ich das wissen Anzahl der Elemente a priori, oder? Dies gilt nicht immer für mein Problem. –

+0

Stimmt, das ist ein Problem. Aber beachten Sie, dass Sie die Anzahl der Elemente * a priori * kennen müssen, wenn Sie Arrays auf dem Stack erstellen. –