如何转发声明命名空间中的类

How to forward declare a class which is in a namespace

本文关键字:命名空间 声明 何转发 转发      更新时间:2023-10-16

我正在尝试在头文件中使用前向声明来减少使用的#include数量,从而减少用户包含我的头文件时的依赖性。

但是,我无法转发声明使用命名空间的位置。 请参阅下面的示例。

文件a.hpp

#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

#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

#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

#include "consumer.hpp"
#include "a.hpp"
consumer::consumer(const char* const text) : a_(text) {}
void consumer::chat() const {
   a_.talk();
}

测试文件main.cpp

#include "consumer.hpp"
int main() {
   consumer c("My message");
   c.chat();
   return 0;
}
<小时 />

更新:

这是我使用以下答案的非常人为的工作代码。

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

在命名空间中转发声明类类型 a ns1

namespace ns1
{
    class a;
}

在多个级别的命名空间中转发声明类型:

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

您使用的是a consumer的成员,这意味着它需要具体类型,您的前向声明不适用于这种情况。

对于嵌套命名空间,从 C++17 开始,您可以

namespace ns1::ns2::nsN
{
  class a;
}

除了从其命名空间中向前声明类(如@billz所说),请记住在引用前向声明的类时使用该命名空间(前置),或添加using子句:

// B.h
namespace Y { class A; } // full declaration of
// class A elsewhere
namespace X {
    using Y::A;   // <------------- [!]
    class B {
        A* a; // Y::A
    };
}

参考:命名空间和前向类声明