1

For example, when creating a class library, I would like to specify an internal API and a public API for each classes, so I can hide some details from the user. The internal API would be used by other classes in the library, and the public API would be used by the library user.

Is it possible?

subb
  • 1,578
  • 1
  • 15
  • 27
  • I think you'll need to be more clear. What are you trying to do? Abstract words like "library", "public", and "interface" don't mean much without more context. – tenfour Mar 05 '11 at 19:51
  • Look up "pImpl" or "Opaque Pointer", e.g. http://en.wikipedia.org/wiki/Opaque_pointer – Erik Mar 05 '11 at 19:54
  • @tenfour edited. I hope it's clearer. – subb Mar 05 '11 at 20:06

6 Answers6

1

In C++, interface could mean many things. It could mean pure virtual functions that you implement in the derived classes, as in the following example,

class Interface
{
public:
   virtual void f()  = 0 ;
};

class Implementation : public Interface
{
public:
   virtual void f()  {} 
};

--

Or it could mean just public functions in your class:

class A
{
public:
   void f() {}  //public function - an interface that the outside world can 
                //use to talk to your class.
};

You can use either of these and can make use of access-specifiers ( public, protected, private) to make your interfaces public or internal/private!

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • This is what I had in mind after hitting the submit button. However, I was wondering if there was another way. In ActionScript, you can declare a namespace and use it as a visibility modifier. So instead of `public void f()` you can do `internal void f()`, and the `f` function is visible only through the `internal` namespace. Is there a similar construct in C++? – subb Mar 05 '11 at 19:55
  • @Subb: You can write `public: void f()`. That is, the token `public:` before every function just like you write `internal` before function in ActionScript. ( I don't know ActionScript by the way). – Nawaz Mar 05 '11 at 19:58
  • I think you misunderstood me. You can actually specify something else than public as a visibility modifier. – subb Mar 05 '11 at 20:04
  • @Subb: No. C++ doesn't has `internal` as keyword. But then what is in the keyword if some other keyword provides you the functionality? You can also use [unnamed namespace](http://stackoverflow.com/questions/4422507/superiority-of-unnamed-namespace-over-static) if you want to make your classes accessible only from one translation unit! – Nawaz Mar 05 '11 at 20:06
  • Well, I just remembered that internal is a keyword, which makes my point invalid. But you can define something like `my_internal` and use it as a visibility modifier on members of a class. That's the beauty of it : it's a namespace at the member level. – subb Mar 05 '11 at 20:13
  • @Subb: I don't know why you want to code C++ in an ActionScript way. Code C++ in a C++ way. Every language has it's own accent. Try to adopt it. C++ provides different mechanism to achieve what you're talking about. – Nawaz Mar 05 '11 at 20:28
  • That's not what I'm suggesting. I was only wondering if there was something equivalent. – subb Mar 05 '11 at 22:34
  • @Subb: I told you the equivalent. But it seems you want the keyword, same syntax. – Nawaz Mar 05 '11 at 22:48
1

Kind of.

Some libraries use friend classes/functions for this. Each class declares other classes as friends if they need access to more than the "public" interface:

class Car {
    friend class Mechanic;
    private:
        Engine engine;
};

class Mechanic {
    // something involving Car::engine...
};

It's not very pretty, but it works.


Another approach that might work for you is the pimpl (pointer-to-implementation) idiom:

class CarImpl; // declaration only

class Car {
    private:
        CarImpl *impl;
    public:
        CarImpl *getImpl(); // doesn't strictly belong in the pimpl pattern
        // methods that simply call the corresponding methods on impl
};

The internal interface can be accessed through a getImpl() call. You would put the CarImpl declaration in a header file that is clearly marked as internal, so clients won't access it. For example, you could put such headers in a subdirectory called internal.

The obvious drawback is that the Car class has a bunch of trivial methods that you have to implement.


A third approach, that I do not recommend, is inheritance:

class Car {
    public:
        virtual void start() = 0;
        static Car *create();
};

And in an internal header:

class CarImpl : public Car {
    public:
        virtual void start();
};

The Car class only exposes the public interface; to get access to the internal interface, internal code needs to do a downcast to CarImpl. This is ugly.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • That is not the pimpl idiom. You never expose the pimpl; if you do it defeats its whole purpose. – wilhelmtell Mar 05 '11 at 20:04
  • If you expose the pimpl but not the definition of its type, it defeats only a third of the purpose, I guess. It still allows for efficient compilation; it still allows for exposing of only part of the interface; it just doesn't allow for switching to a different implementation. – Thomas Mar 05 '11 at 20:05
1

You can use many tricks to grant friendship or an "extended" interface to a given few, however it is soon cumbersome.

The simplest way to separate the external interface from the internal interface... is to have two interfaces, thus two classes.

If you take a peek at the set of Design Patterns proposed by the GoF, you'll notice the Proxy pattern.

You can use this by not exposing the class to the exterior of your library, but instead exposing a Proxy, in which you wrap the class, and which only exposes a subset of its interface.

class MyClass
{
public:
  void foo();
  void bar();

  void printDebugInfo();
  void test();
};

class MyClassProxy
{
public:
  MyClassProxy(std::unique_ptr<MyClass> ptr): _ptr(ptr) {}

  void foo() { _ptr->foo(); }
  void bar() { _ptr->bar(); }

private:
  std::unique_ptr<MyClass> _ptr;
};

I personally find this design rather clean. No down-casting, No subtle inheritance trick, No friendship list longer than my arm.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
0

I'm not quite sure what you're asking, but if you have an abstract class defined:

class Loggable { ... };

You can inherit from it privately, like this:

class User : private Loggable { ... };

The class User now has the members of Loggable, but they are private.

Please see the C++ FAQ lite.

ClosureCowboy
  • 20,825
  • 13
  • 57
  • 71
0

There is a number of ways to approach this. One is runtime polymorphism:

struct widget {
    virtual debug_info diagnose() = 0;
    virtual void draw() = 0;
};

struct window {
    virtual void draw() = 0;
};

struct view : public window, public widget {
    void draw();
    debug_info diagnose();  // internal
};

Or with compile-time polymorphism:

struct view {
    void draw();
    debug_info diagnose();  // internal
};

template<class W>
void do_it(W window)
{
    widget.draw();
}

template<class W>
void diagnose_it(W widget)
{
    debug_info d = widget.diagnose();
}

Another approach is to expose private members to specific functions or classes:

struct widget {
    virtual void draw() = 0;
};

struct view : public widget {
    friend void diagnose_widget(widget w);
    void draw();
private:
    debug_info diagnose();
};

// internal
debug_info diagnose_widget(widget w)
{
    debug_info d = w.diagnose();
}
wilhelmtell
  • 57,473
  • 20
  • 96
  • 131
0

A C++ class has 3 levels of protection: public, protected and private. Public things are accessible to everybody, protected only to descendant -- and then for themselves and not for other descendants --, private for the class and its friend.

Thus friendship is the only way to grant more than public access to a class/function which isn't a descendant, and it grants full access, which isn't always convenient.

An heavy solution which I've used with success was to write a wrapper which was a friend of the main class, and then provided additional access to its own friends (which were the only one able to construct the wrapper). I'm not really recommending it, it is tedious, but it could be useful if you have such a need.

class Main {
public:
    ...
private: // but wrapped
    void foo();
protected:
    ...
private: // and not wrapped
    void bar();
};

class Wrapper {
pubic:
    void foo() { wrapped.foo(); }
private:
    Wrapper(Main& m) : wrapped(ma) {}
    Main& wrapped;
    friend void qux(Main&);
};

void qux(Main& m) {
   Wrapper mwrapped(m)

   mwrapped.foo();
   // still can't access bar
}
AProgrammer
  • 51,233
  • 8
  • 91
  • 143