Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to forward declare a class which is in a namespace

Tags:

c++

namespaces

I am trying to use forward declarations in header files to reduce the number of #include used and hence reduce dependencies when users include my header file.

However, I am unable to forward declare where namespaces are used. See example below.

File 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__ 

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

File 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__ 

Implementation file consumer.cpp:

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

Test file main.cpp:

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

UPDATE:

Here is my very contrived working code using the answer below.

File 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__ 

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

File 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__ 

File 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(); } 

File main.cpp:

#include "consumer.hpp"  int main() {    consumer c("My message");    c.chat();    return 0; } 
like image 799
Angus Comber Avatar asked Sep 25 '13 09:09

Angus Comber


People also ask

Can you forward-declare a namespace?

There is no forward declaration of namespace.

Can you forward-declare a class?

In C++, classes and structs can be forward-declared like this: class MyClass; struct MyStruct; In C++, classes can be forward-declared if you only need to use the pointer-to-that-class type (since all object pointers are the same size, and this is what the compiler cares about).

Can we declare class inside namespace?

A class can also be declared inside namespace and defined outside namespace using the following syntax: CPP.

How do you define a class in namespace?

Classes are data types. They are an expanded concept of structures, they can contain data members, but they can also contain functions as members whereas a namespace is simply an abstract way of grouping items together. A namespace cannot be created as an object; think of it more as a naming convention.


2 Answers

To forward declare class type a in a namespace ns1:

namespace ns1 {     class a; } 

To forward declare a type in multiple level of namespaces:

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

Your are using a a member of consumer which means it needs concrete type, your forward declaration won't work for this case.

like image 130
billz Avatar answered Sep 20 '22 05:09

billz


For nested namespaces, since C++17, you can do

namespace ns1::ns2::nsN {   class a; } 
like image 40
user2193043 Avatar answered Sep 22 '22 05:09

user2193043