1
votes

I'm fairly new to C++ inheritance, and I'm using boost sockets. I want to create something comparable to Java's DataOutputStream for a synchronous boost socket. Namely, I want methods like SendInt, ReadLong, etc. I tried making a class that inherits from the socket, but I keep getting errors. Right now, I have something like this:

DataSocketStream.h

#include "boost/asio.hpp"
#include <vector>
namespace Server {
using namespace std;
namespace as = boost::asio;
namespace ip = boost::asio::ip;
class DataSocketStream : public ip::tcp::socket{
public:
    DataSocketStream(as::io_service);
    virtual ~DataSocketStream();
    void WriteInt(int);
    void WriteLong(long);
    int ReadInt(boost::system::error_code);
    long ReadLong(boost::system::error_code);
    void Flush (boost::system::error_code);
    string ReadString(boost::system::error_code);
    double ReadDouble(boost::system::error_code);
    void WriteDouble(double);
private:
    ip::tcp::socket* socketFormPtr
    std::vector<char> Message;
};

DataSocketStream.cpp

#include "DataSocketStream.h"

namespace Server {
namespace as = boost::asio;
namespace ip = boost::asio::ip;
using namespace std;
DataSocketStream::DataSocketStream(as::io_service ios)
: ip::tcp::socket(ios)
{
    socketFormPtr = this;

}

DataSocketStream::~DataSocketStream()
{

}

void DataSocketStream::WriteInt(int toWrite){
    //Implementation that pushes the bytes onto the vector Message
}
void DataSocketStream::WriteLong(long toWrite){
    //...
}

void DataSocketStream::Flush(boost::system::error_code e)
{
    as::write(*socketFormPtr, as::buffer(Message), as::transfer_all(),e);
    delete (&Message);
    std::vector<char> Message;
}

int DataSocketStream::ReadInt(boost::system::error_code e)
{
    char Af[4];
    as::read(*socketFormPtr, as::buffer(Af), e);
    return ((Af[0]<<24)| (Af[1]<<16) | (Af[2]<<8) | (Af[3]));

}

long DataSocketStream::ReadLong(boost::system::error_code e)
{
    //...
}

string DataSocketStream::ReadString(boost::system::error_code e)
{
    //...
}

double DataSocketStream::ReadDouble(boost::system::error_code e)
{
    //...
}
void DataSocketStream::WriteDouble(double val)
{
    //...
}
} 

However, when I try something like as::io_service io_service; DataSocketStream CLsocket(io_service);

The compiler gives me an error, error: 'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)' is private I figured that has something to do with my class not being a part of the boost library.

I tried inheriting from other boost::asio::basic_stream_socket, but I got errors doing that too. (It was a very strange 'Invalid use of "::" ' error) I also tried creating a normal boost::asio::ip::tcp::socket and then casting the pointer to a pointer of DataSocketStream, but that didn't work either.

I know that I could do all this in the form of helper methods like:

int ReadInt(boost::asio::ip::tcp::socket* S, boost::system::error_code e)
{
    char Af[4];
    as::read(*S, as::buffer(Af), e);
    return ((Af[0]<<24)| (Af[1]<<16) | (Af[2]<<8) | (Af[3]));

}

but the inheritance way seems to be the better design. Is there something I am missing, or is the boost library really not designed to be extended in the way I am trying? Thanks!

1
Sam Miller has posted the answer to your question. However I would like to add that composition is preferable over inheritance here -- DataSocketStream should simply wrap an existing socket instead of inheriting a socket, since the "stream" is not a type of socket itself, it just provides additional functionality over a socket.casablanca
@casablanca Could you explain the wrapping an existing socket more? It sounds interesting, but I'm not sure I understand how it would be different.0xFE
By wrapping, I mean have a member variable of type socket instead of inheriting from socket and use this variable in your functions. Then, instead of passing io_service to the constructor, you would just directly pass the socket. It's always nice to avoid inheritance when you don't really need it.casablanca

1 Answers

1
votes

   

DataSocketStream(as::io_service);

An io_service is noncopyable as the error suggests, pass it by reference

DataSocketStream(as::io_service&);
                               ^