C++ Abstraction OOP (Inherit only some method to derived class) - c++

Suppose i have a socket class:
class Socket{
public:
... Some Code ...
Socket(int type){
isServer = type;
//some code
}
virtual void Send(string s);
virtual void Send(string s, int clientID);
... Some Code ...
private:
int isServer;
};
This is to be used both as a server and client.
Now I need to have 2 Derived classes:
class ClientSocket : public Socket{
public:
... Some Code ...
};
class ServerSocket : public Socket{
public:
... Some Code ...
};
What I want is that ClientSocket will only have access to Send(string) and server socket will only have access to Send(string, int)
I checked some other answer:
https://stackoverflow.com/a/20997981/14911094
And that has a good idea of not using inheritance at all rather just encapsulate(Have a socket instance in server). But I want to know whether this can be done using Inheritance.

There is not absoulte way to doing such thing.
But here my idea:
create two class(like interface):
first class is server socket sender:
Class ServerSocketSender {
public:
virtual void Send(string s, int clientID);
}
second class is client socket sender:
Class ClientSocketSender {
public:
virtual void Send(string s);
}
due to interface segregation principle i recommend you to do such thing it is not wise choice to combine two send method in one class and enable desire method in desire class.
another trick that i saw many times but i dont know exactly if it's work in your case or not is something called SFINAE. with this trick i think you can achieve same thing but due to complexity i not recommend this approach.

Related

which design pattern to use to get the wanted functionality

I want to make a pure virtual class that other classes inherit and each class implements the same function but with different implementation:
let say I implement class Server
class Server
{
Server();
~Server()=0;
virtual void send(const std::string& string);
virtual std::string receive();
};
class TcpServer:public Server
{
TcpServer();
~TcpServer();
void send(const std::string& string)
{...}
std::string receive(){...}
};
class UdpServer : public Server
{
UdpServer ();
~UdpServer ();
void send(const std::string& string)
{...}
std::string receive(){...}
};
main()
{
Server* server = new TcpServer()/UdpServer;
}
What's this Design Pattern called? because I don't understand if it's Adapter or Composite or Facade and if you have a different idea of how to implement this behavior.
Strategy pattern should be implemented for this use case. Check the link below for more information.
https://en.m.wikipedia.org/wiki/Strategy_pattern
I would lean more towards Factory Pattern:
https://en.m.wikipedia.org/wiki/Factory_method_pattern
Since you go into TCP/ UDP you might also check out the reactor pattern

Running into c++ virtual template function issue due to interface based programming

We are designing a new system where we have created interfaces for most of our classes so that we can create mocks (google mocks) for them for unit testing. As a result, all the functions are virtual but the issue is that I am often running into template virtual function issue due to this. I have seen some examples on how to do multi dispatch but they all seem to be using some variation of templates, it doesn't seem straightforward. So does it mean that my entire codebase will now end up with templates making it difficult to read/use and debug?
Or am I not designing good interfaces. Here is a simple example where I am writing an interface for a message queue.
Class IMessageQueue {
Public:
Virtual int send(const T & value); // I can't do this but this is exactly what I want to do, as send should be able to send any type
};
Class MessageQueue : public IMessageQueue {
Public:
Virtual int send(const T & value) { ... }
};
Class MockMQ : public IMessageQueue {
Public:
Virtual int send(const T & value) {
// mock implementation
}
};
How do I get around this problem? This is just one example but I run into lots of these type of issues due to interface based programming.
It depends if you need your IMessageQueue to dispatch specific unknown type or any type. That's not the same thing.
A specific unknown type can be managed by
template<typename T>
class IMessageQueue {
public:
virtual int send(const T& value);
}
So that you can have your IMessageQueue<MyMessage> and IMessageQueue<OtherMessage>.
If, instead, you need to be able to send any type with the same type of message queue then your option is to declare a specific interface common to all messages as in
class Message
{
protected:
Message() : { .. }
};
class MyMessage : public Message
{
..
};
class MessageQueue
{
public:
void send(const Message& message);
};

Opaque Pointer (pimpl) and signals and slots

I am getting more and more into the Pimpl idiom (private opaque pointer to real class implementation). But I still have an issue which bothers me.
How does this idiom\design pattern deal with signals in the public class (like boost or qt signals)?
class my_class : public QObject
{
Q_OBJECT
public:
void monitorstuff();
signal:
void needupdate();
private:
class impl; unique_ptr<impl> pimpl; // opaque type here
};
class my_class::impl {
void reallymonitorstuff();
};
my_class::impl::reallymonitorstuff()
{
...
//update required here
...
}
void my_class::monitorstuff()
{
pimpl->reallymonitorstuff();
}
Do I replicate all signals in the pimpl, connect with signals of the outer class? A bit annoying to have twice as much signals as what is publicly available, also annoying when I need to swap instances.
Do I pass the public instance as parameter to the private instance which calls directly the public signals
Another design mechanism in conjuction I didn't heard of?
In general, I don't really see the problem. The public class should forward all calls to the impl including calls to connect a slot. The impl contains the signal, not the public class. E.g here using Boost.Signals2:
#include <memory>
#include <boost/signals2.hpp>
#include <iostream>
using signal_type = boost::signals2::signal<void()>;
using slot_type = signal_type::slot_type;
class my_class {
public:
my_class();
void monitorstuff();
void connect(const slot_type& slot);
private:
struct impl; std::unique_ptr<impl> pimpl;
};
struct my_class::impl {
signal_type signal;
void reallymonitorstuff();
void connect(const slot_type& slot){ signal.connect(slot); }
};
void
my_class::impl::reallymonitorstuff() {
//...
signal();
//...
}
void my_class::monitorstuff() {
pimpl->reallymonitorstuff();
}
void my_class::connect(const slot_type& slot) {
pimpl->connect(slot);
}
my_class::my_class() : pimpl(std::make_unique<my_class::impl>()){}
int main() {
my_class mc;
auto slot = []{ std::cout << "Notified!\n"; };
mc.connect(slot);
mc.monitorstuff();
}
Live demo.
I wonder if your problem is more specific to Qt.
Do I replicate all signals in the pimpl, connect with signals of the outer class? A bit annoying to have twice as much signals as what is publicly available, also annoying when I need to swap instances.
No, you don't need to do that.
Do I pass the public instance as parameter to the private instance which calls directly the public signals
That is not necessary either.
Another design mechanism in conjuction I didn't heard of?
That is not necessary either.
Assuming my_class::monitorstuff is supposed raise a signal, I think all you need is:
void my_class::monitorstuff()
{
pimpl->reallymonitorstuff();
emit <<Details of signal>>;
}
pimpl does not need to be concerned with signals or slots.

C++ Instantiate subclass from multiple choices

I'm using a library that implements different types of network protocols like in the following simplified example that hopefully illustrates the problem I have. NOTE: This is all pseudo code just to show the overall problem.
class Network
{
virtual void connect() {...}
void readPacket() = 0;
};
class NetworkClient : public Network
{
virtual void connect(int ip, int port) {super::connect() ...}
};
class NetworkServer : public Network
{
virtual void connect(int port) {super::connect() ...}
};
class ProtocolAClient : public NetworkClient
{
void readPacket() {...}
};
class ProtocolAServer : public NetworkServer
{
void readPacket() {...}
};
class ProtocolBClient : public NetworkClient
{
void readPacket() {...}
};
class ProtocolBServer : public NetworkServer
{
void readPacket() {...}
};
Now in my application, I want to have a Client and a Server, which should be either a ProtocolA or ProtocolB client/server, depending on which protocol the user chooses to connect with.
So I thought I could create my application classes like this.
class AppClient : public NetworkClient
{
... custom functionality needed by the app client ...
void sendAppData(...)
};
class AppServer : public NetworkServer
{
... custom functionality needed by the app server ...
void sendAppData(...)
};
Then I thought that when I need a client, for example, in the application I could just do this.
AppClient *client;
if(useProtocalA)
client = new ProtocolAClient;
else
client = new ProtocolBClient;
client->sendAppData();
However the compiler quickly let me know that this is not possible since ProtocolAClient and ProtocolBClient are not an AppClient. Here is the exact compiler error.
error C2440: '=' : cannot convert from 'ProtocolAClient *' to 'AppClient *'
So my next idea was to make AppClient and AppServer template classes, but that doesn't work either as you can't get a pointer to the instance as the pointer doesn't have a template argument like this.
AppClient *client; <--- Uh oh... missing template argument!
if(useProtocalA)
client = new AppClient<ProtocolAClient>;
else
client = new AppClient<ProtocolBClient>;
client->sendAppData();
This seems like it should be such a simple problem to solve, but I just can't seem to see the solution.
So you have the following classes:
class Network
{
virtual void connect() {...}
void readPacket() = 0;
}
class NetworkClient : public Network
{
virtual void connect(int ip, int port) {super::connect() ...}
}
class AppClient : public NetworkClient
{
... custom functionality needed by the app client ...
void sendAppData(...)
}
class ProtocolAClient : public NetworkClient
{
void readPacket() {...}
}
class ProtocolBClient : public NetworkClient
{
void readPacket() {...}
}
The problem is that you want an AppClient object, but the ProtocolAClient is of type NetworkClient and not type AppClient.
Your inheritance looks like this:
Network ---- NetworkClient ---- ProtocolAClient
|---- ProtocolBClient
|---- AppClient
As you can see, neither ProtocolAClient nor ProtocolBClient is of type AppClient, but all of them are of type NetworkClient.
So, if you want this code to work:
AppClient *client;
if(useProtocalA)
client = new ProtocolAClient;
else
client = new ProtocolBClient;
client->sendAppData();
you will have to do the one of the following changes:
A) change your ProtocolAClient and ProtocolBClient to inherit the AppClient class:
class ProtocolAClient : public AppClient
{
void readPacket() {...}
}
class ProtocolBClient : public AppClient
{
void readPacket() {...}
}
Now your inheritance looks like this:
Network ---- NetworkClient ---- AppClient ---- ProtocolAClient
|---- ProtocolBClient
or B) - Recommended: don't use AppClient as you already have NetworkClient:
NetworkClient*client;
if(useProtocalA)
client = new ProtocolAClient;
else
client = new ProtocolBClient;
client->sendAppData();
I think I'd stop right at:
class Network {};
class NetworkClient : public Network {};
class NetworkServer : public Network {};
At first glance, this already looks like a serious problem. Public inheritance implies the Liskov Substitution Principle--you should be able to substitute an instance of the derived class anywhere an instance of the base class is needed.
A NetworkClient (or a NetworkServer) is not a network, and I doubt there's even one circumstance in which either can be substituted for a network (not to mention all possible circumstances). As such, it seems to me that your basic design is problematic from the beginning.
My immediate reaction would be that you probably want something like:
class ProtocolA {};
class ProtocolB {};
template <class Protocol>
class Client {};
template <class Protocol>
class Server {};
With this, you can fairly easily instantiate a client or server using either protocol. This does not, however, support run-time substitution. That is to say, you don't get anything like a base class that lets you deal completely transparently (at runtime) with an object that may be any of two or more different types.
If you really need that, you probably want something more like:
class Protocol {};
class ProtocolA : public Protocol {};
class ProtocolB : public Protocol {};
class Client {
Protocol *p;
public:
Client(Protocol *p) : p(p) {}
};
class Server {
Protocol *p;
public:
Server(Protocol *p) : p(p) {}
};
[aside: despite following the syntax reasonably closely, this is really pseudo-code not C++. You clearly need to add a number of other things like virtual destructors before the code can actually be used at all.]
Then you instantiate an instance of the correct Protocol, and pass (a pointer to) that instance to create a Client or Server object.
With either of these, the Client/Server uses the Protocol to do communication, but (unlike with public inheritance) we have not made nonsensical assertions about being able to substitute a Client/Server for a network (or network protocol).
For me, your class hierarchy isn't precisely defined. In particular: what exactly is the NetworkClient class and what are you going to use it for? If this is to be used so that client->sendAppData() has to be called, then ProtocolAClient class should not derive from it. This solution you gave seems the best:
AppClient *client; <--- Uh oh... missing template argument!
if(useProtocalA)
client = new AppClient<ProtocolAClient>;
else
client = new AppClient<ProtocolBClient>;
client->sendAppData();
But you say you lack the ability to have this AppClient without specifying the protocol client class.
You can solve this problem by using virtual-template-pair idiom (or whatever name is used for it):
class AppClient { /* ... */ virtual void sendAppData() = 0; };
template <class ProtocolClientClass>
class AppClientSpec: public AppClient
{
/* ... */
ProtocolClientClass* inproto; // or whatever...
virtual void sendAppData() { return inproto->sendAppData(); }
};
And now your example can be fixed as:
AppClient *client; <--- Uh oh... missing template argument!
if(useProtocalA)
client = new AppClientSpec<ProtocolAClient>;
else
client = new AppClientSpec<ProtocolBClient>;
client->sendAppData();

Member variable of subtype of base class in base class

Is there a way to do the following with templates? The following code throws unknown type compile time errors.
I'm trying to create two different types of Application, those that inherit from Application, and those that inherit from Service, which inherits from Application. All Applications have one service called Cron, which will inherit from Service. Applications will be threaded and detached, while Services that derive from Application will be threaded and joined. I broke this down to simplest terms.
#include <iostream>
class Application
{
public:
Service service; //Throws unknown type... Forward decl. will not work either.
};
class Service:public Application
{
};
int main(int argc, const char * argv[])
{
// insert code here...
std::cout << "Hello, World!\n";
return 0;
}
Thanks,
Bruce
No, there is no way to do what you want, because what you want to do is nonsense. Hold on, I'll explain.
Service is derived from Application, but Application has a member of type Service.
This is a cyclic dependancy but beyond that, I just don't understand it. Since Service is derived from Application, which has a member of type Service, which is derived from Application, which has a member of type Service... you get the idea. It's like standing in front of a mirror with a mirror and trying to find the end.
Now the question becomes, what are you really trying to do?
In your comments, you said:
I'm trying to create two different types of Application, those that
inherit from Application, and those that inherit from Service, which
inherits from Application. All Applications have one service called
Cron, which will inherit from Service.
There's still a little ambiguity here. How can Application derive from Application?
I suspect that what you're after is having two different concrete instantiations of the class which implements Service. One only implements Service, and the other implements other stuff too.
In that case:
class Service
{
public:
void Cron();
};
class Application
{
public:
void OtherStuff();
};
But you also said:
Applications will be threaded and detached, while Services that derive
from Application will be threaded and joined.
That sounds like a job for a policy-based design.
class DetatchedPolicy
{
public:
void StartThread(); // this function would start the thread and detatch
};
class JoinedPolicy
{
public:
void StartThread(); // this function would start the thread and join
};
template <typename ThreadingPolicy>
class BasicService
:
public ThreadingPolicy
{
public:
Service()
{
StartThread();
}
void Cron();
};
typedef BasicService <JoinedPolicy> Service;
typedef BasicService <DetatchedPolicy> Application;
I think what you actually want to do is to use a pointer.
class Service;
class Application
{
std::shared_ptr<Service> m_service;
};
class Service : public Application
{
};
It sounds to me like you may benefit from separating the interfaces from the implementations:
struct ApplicationInterface
{
virtual ~ApplicationInterface() {}
virtual void do_application_stuff_1() = 0;
virtual void do_application_stuff_2() = 0;
};
struct ServiceInterface
: public ApplicationInterface
{
virtual ~ServiceInterface() {}
virtual void do_service_stuff_1() = 0;
virtual void do_service_stuff_2() = 0;
};
class CronService
: ServiceInterface
{
public:
// ApplicationInterface
virtual void do_application_stuff_1() {}
virtual void do_application_stuff_2() {}
// ServiceInterface
virtual void do_service_stuff_1() {}
virtual void do_service_stuff_2() {}
};
class Application
: ApplicationInterface
{
protected:
CronService cron;
public:
virtual void do_application_stuff_1() {}
virtual void do_application_stuff_2() {}
};