6

I want to know if I can split a C++ class declaration

Original class

    class P
    {
        private: 
           int id;
           //some really secret method
           int secretMethod();
       protected:
           int x;
       public:
           P();
           int getX();
    };

I want to show in the .h only the public and protected method and attributes, and declare somewhere else the private, where the user of the class can't see it.

Wanted class declaration:

    class P
    {
       protected:
           int x;
       public:
           P();
           int getX();
    };

Edit: I want that for:

  1. I can change the implementation of the class and for the user of the class is transparent
  2. Is easier for the user to see less information than more
  3. If I change the implementation of the class, change the private atributes and method I don't want to change the .h for the user of the class
Troncador
  • 2,856
  • 2
  • 18
  • 39

5 Answers5

5

Yes, it is possible but not in the direct kind of way. Here is what you do:

my_object.h:

struct my_object {
  void fun();

  my_object();
  my_object(my_object const&);
  ~my_object();

  my_object& operator = (my_object);

protected:
  void pfun();

private:
  struct impl;
  std::unique_ptr<impl> pimpl;
};

my_object.cpp:

struct my_object::impl {
  void fun() { do stuff...}

  void pfun() { do other stuff... }

  int private_member;
};

my_object::my_object() : pimpl(new impl) {}
my_object::my_object(my_object const& o) : pimpl(new impl(*o.pimpl) {}
my_object::~my_object() {}

my_object& my_object::operator = (my_object o) { swap(pimpl, o.pimpl); return *this; }

void my_object::fun() { pimpl->fun(); }
void my_object::pfun() { pimpl->pfun(); }

As you can see, it's a lot of work and requires the heap. Everything in balance...use when you need to.

Edward Strange
  • 38,861
  • 7
  • 65
  • 123
1

If your purpose is to simply reduce clutter in your header, you can include a file in the middle of your class:

class P
{
#include "P.private_parts"

   protected:
       int x;
   public:
       P();
       int getX();
};
Benjamin Lindley
  • 95,516
  • 8
  • 172
  • 256
  • Humn.. I think P.private_parts can't be secret. – Troncador May 04 '12 at 23:08
  • @Troncador: I wasn't sure what your reason was for wanting to hide the private data, since you didn't elaborate on that when Tibor asked. One possible reason would be that you just wanted your header file less cluttered, so I answered how to fix that. So in the future, please answer questions that people ask you in the comments under your post, so that everyone can be clear of what you are really trying to accomplish. – Benjamin Lindley May 04 '12 at 23:21
  • However code completion won't work in `P.private_parts` if you want to access members for instance... – Jean-Michaël Celerier Mar 03 '14 at 14:48
0

Something like this?

class P
{
private:
    class Impl
    {
    public:
       int id;
       //some really secret method
       int secretMethod();
    };

private:
    Impl* _pimpl;

protected:
    int x;

public:
    P() : _pimpl(new P::Impl()) {}
    ~P() { delete _pimpl; } 
    int getX();

};
ervinbosenbacher
  • 1,491
  • 12
  • 15
  • No, no, no. That's not splitting a class at all. Not to mention the fact that Impl's definition is still known to the header... – Puppy May 04 '12 at 21:42
  • Thank you for the comment. Probably I was too quick. – ervinbosenbacher May 04 '12 at 21:46
  • 1
    I would recommend against using the '\_' prefix in your code unless you're working on the standard library. Although in this case, because it's not in global scope, it's OK there are many cases when you'll run into IDB, generally exposed as name clashes. The '\_' prefix has special meaning and depending on scope and what follows after it...you could be writing an ill-formed program. Best to just avoid the whole thing by not using that prefix at all. – Edward Strange May 04 '12 at 22:40
0

It is not possible to genuinely split a C++ class definition. All that you can do is implement a run-time abstraction which will firewall the source code by using a disgusting hack like PIMPL.

Puppy
  • 138,897
  • 33
  • 232
  • 446
  • 7
    I'm sure you have valid reasons for why you think the Pimpl idiom is terrible. It would be great if you elaborated on those so the OP could make a reasoned decision. – Benjamin Lindley May 04 '12 at 21:50
  • @BenjaminLindley: Not my answer, but the Pimpl idiom - like the Singleton pattern - suffers from overuse. It's one thing to isolate implementation from your *public* interface (i.e., what clients of your library will see in /usr/include/MyLib). It's quite another when you find that *every* class in a code base has been "pimpled", as it makes the source unwieldly and unnecessarily difficult to debug, for very little gain. – DevSolar Mar 14 '13 at 06:27
0

You can heritage the second part like this:

//Class P_Hetitage definition

class P_Heritage {
      protected:
                int id;
                //some really secret method
                int secretMethod();
}

//Class P definition

class P : private P_Heritage {
      protected:
                int x;
      public:
             P();
             int getX();
};

Below a straightforward explanation how inheritance works:

Inheritance the class P_Heritage as:

public

  1. public elements are public to class P
  2. protected elements are private to class P

private

  1. public elements are private to class P
  2. protected elements are private to class P

P_Heritage's private elements can not be seen by class P

TheArchitect
  • 975
  • 2
  • 14
  • 23