Kushagra Gupta
Kushagra Gupta

Reputation: 614

Declare a private method on a public class which takes arguments of private type

I am writing a socket library in C++-17 which has a public class Socket (i.e. I declare it in the .hpp file). This class is supposed to be the interface between the user and the library.

I have a private type (declared in the .cpp file) Packet which is used to represent a packet in memory. The type Socket has a few private helper methods which take Packet as an argument.

If I try to only declare the helper method in the .cpp file, the compiler complains that no such member exists. If I try to declare the method in the .hpp then I cannot name the argument type as it is supposed to be private.

This is the public class declaration (in .hpp):

class Socket {
 private:
  // ...private attributes
  // void serialize(Packet p, uint8_t buffer[64]); // This is the helper function. `Packet` is private type
 public:
  // ...constructors and stuff
}

This is how I tried to define the function in the implementation file:

void Socket::serialize(Packet p, uint8_t buffer[64]) {
 // ...a lot of things
}

How should I go about declaring such functions without making the library internals public.

Upvotes: 1

Views: 313

Answers (2)

Chuck Batson
Chuck Batson

Reputation: 2774

This can be implemented using a forward declaration, which takes advantage of the fact that in C++ it is legal to use pointers and references to incomplete types.

Here's an example of how it would look in your situation.

include/socket.hpp

// Public-facing include file

#include <cstdint>

class Packet; // forward declaration

class Socket {
  private:
    // ...private attributes
    void serialize(const Packet & p, uint8_t buffer[64]); // This is the helper function. `Packet` is private type
  public:
    // ...constructors and stuff
};

private/socket.cpp

#include "socket.hpp"
#include "packet.hpp"

void Socket::serialize(const Packet & p, uint8_t buffer[64]) {
 *reinterpret_cast<int *>(buffer) = p.value; // note access of Packet member
}

private/packet.hpp

// Private (i.e., library local) definition of Packet

class Packet {
  public:
    int value;
};

The file private/packet.hpp is not shipped with the library. Thus, to includers of include/socket.hpp, Packet will be an opaque type.

Upvotes: 0

Salvage
Salvage

Reputation: 509

You could make Packet a nested private class of Socket, meaning it wouldn't be exposed to the users of your library.

class Socket {
    private:
        class Packet {
            ...
        };
    public:
        ...
};

Upvotes: 1

Related Questions