web-dev-qa-db-fra.com

Comment transférer une classe qui se trouve dans un espace de noms

J'essaie d'utiliser des déclarations en aval dans les fichiers d'en-tête pour réduire le nombre d'inclusions utilisées et, partant, pour réduire les dépendances lorsque les utilisateurs incluent mon fichier d'en-tête.

Cependant, je suis incapable de transférer decalre lorsque des espaces de noms sont utilisés. Voir exemple ci-dessous.

a.hpp file:
#ifndef __A_HPP__
#define __A_HPP__

namespace ns1 {

   class a {
   public:
      a(const char* const msg);

      void talk() const;

   private:
      const char* const msg_;
   };
}

#endif //__A_HPP__

a.cpp file:
#include <iostream>

#include "a.hpp"

using namespace ns1;

a::a(const char* const msg) : msg_(msg) {}

void a::talk() const { 
   std::cout << msg_ << std::endl; 
}



consumer.hpp file:
#ifndef __CONSUMER_HPP__
#define __CONSUMER_HPP__

// How can I forward declare a class which uses a namespace
//doing this below results in error C2653: 'ns1' : is not a class or namespace name
// Works with no namespace or if I use using namespace ns1 in header file
// but I am trying to reduce any dependencies in this header file
class ns1::a;

class consumer
{
public:
   consumer(const char* const text) : a_(text) {}
   void chat() const;

private:
   a& a_;
};

#endif // __CONSUMER_HPP__

consumer.cpp implementation file:
#include "consumer.hpp"
#include "a.hpp"

consumer::consumer(const char* const text) : a_(text) {}

void consumer::chat() const {
   a_.talk();
}

test - main.cpp file:
#include "consumer.hpp"

int main() {
   consumer c("My message");
   c.chat();
   return 0;
}

METTRE À JOUR:

Voici mon code de travail très artificiel utilisant la réponse ci-dessous.

a.hpp:
#ifndef A_HPP__
#define A_HPP__

#include <string>

namespace ns1 {

   class a {
   public:
      void set_message(const std::string& msg);
      void talk() const;

   private:
      std::string msg_;
   };

} //namespace

#endif //A_HPP__

a.cpp:
#include <iostream>
#include "a.hpp"

void ns1::a::set_message(const std::string& msg) {
    msg_ = msg;
}
void ns1::a::talk() const { 
   std::cout << msg_ << std::endl; 
}

consumer.hpp:
#ifndef CONSUMER_HPP__
#define CONSUMER_HPP__

namespace ns1
{
   class a;
}

class consumer
{
public:
   consumer(const char* text);
   ~consumer();
   void chat() const;

private:
   ns1::a* a_;
};

#endif // CONSUMER_HPP__

consumer.cpp:
#include "a.hpp"
#include "consumer.hpp"

consumer::consumer(const char* text) {
   a_ = new ns1::a;
   a_->set_message(text);
}
consumer::~consumer() {
   delete a_;
}
void consumer::chat() const {
   a_->talk();
}


main.cpp:
#include "consumer.hpp"

int main() {
   consumer c("My message");
   c.chat();
   return 0;
}
34
Angus Comber

Pour transmettre le type de classe de déclaration a dans un espace de noms ns1:

namespace ns1
{
    class a;
}

Pour transférer, déclarez un type dans plusieurs niveaux d'espaces de nom:

namespace ns1
{
  namespace ns2
  {
    //....
     namespace nsN
     {
        class a;
     }
    //....    
  }
}

Vous utilisez a un membre de consumer, ce qui signifie qu'il nécessite un type concret, votre déclaration forward ne fonctionnera pas dans ce cas.

47
billz

En dehors de la déclaration en avant de la classe à partir de son espace de noms (comme le dit @billz), pensez à utiliser use (prepend) cet espace de noms lors de la référence à la classe déclarée en aval, ou à ajouter une clause using:

// B.h
namespace Y { class A; } // full declaration of
// class A elsewhere

namespace X {
    using Y::A;   // <------------- [!]
    class B {
        A* a; // Y::A
    };
}

Ref: Espaces de nommage et déclarations de classes directes

0
Campa