How to implement pure virtual functions with different parameter structures - c++

I'm building a class with pure virtual functions called Database. The idea is to have a class that handles all the database interfaces (ie: open and close) and can be used on my business layers.
The Database class will be implemented in several 'flavours' for different databases, like mySqlDatabase and OracleDatabase.
I imagined Database having pure virtual methods with no code - just a header file as follows:
Database.hpp
class Database {
public:
Database();
virtual ~Database();
virtual void open(const std::string databasename) = 0;
virtual void open(const std::string databasename, const std::string username, const std::string password) = 0;
virtual void open(const std::string databasename, const std::string schema, const std::string username, const std::string password) = 0;
.
<Other stuff>
.
}
The three open variations are there to support different database connection requirements, from the simplest one (like Sqlite3 that needs only a filename), to Oracle (that needs all of that variables to connect).
I have some questions about the implementations (let's take oracle for example):
a) Shall I need to redeclare the virtual methods again on the derived class header file, like:
class OracleDatabase : public Database {
public:
OracleDatabase ();
virtual ~OracleDatabase ();
void open(const std::string databasename);
void open(const std::string databasename, const std::string username, const std::string password);
void open(const std::string databasename, const std::string schema, const std::string username, const std::string password);
}
b) How do I structure the implementation of the open methods in the derived class (let´s take Sqlite3)?
void Sqlite3Database::open(const std::string databasename){
...do some stuff...
}
void Sqlite3Database::open(const std::string databasename, const std::string username, const std::string password) {
...do some stuff...
}
void Sqlite3Database::open(const std::string databasename, const std::string schema, const std::string username, const std::string password) {
...do some stuff...
}
Am I using the right strategy? I've been browsing around virtual and pure virtual strategies and think this is the best approach for my problem.
Any suggestions/hints?
OBS: I'm coming from C# world so I do apologize if there is some misconception here.

For writing query functions (ie. same interface for all databases), pure virtual functions are the way to go.
Here, you are trying to write an open function, for which you might want to consider the Factory Design Pattern: you write your Database withour any open function; and you write a function such as static std::unique_ptr<Database> Sqlite3Database::open(/*...*/).
Using a virtual function like the one you are advocating is not a good idea: anyway you have 3 different functions that completely depend on the database that is used; and worse, your mother class depends on its children: to add a new database with another logging scheme, you have to add a function prototype to Database.
Another way to go would be to use a pure virtual function (preferably protected and called from constructor to preserve RAII; and following the NVI idiom) that takes as argument an initialization string such as the one used by PDO. Not exactly the same as anyway the database type can be inferred from the type instantiated, but the idea is to keep a single argument so as not to have multiple versions of open
(Old answer kept for the principles it tried to explain)
Actually you can do much easier: forget about open, and just do all of your initialization inside Sqlite3Database::Sqlite3Database(/* ... */).
After all, there is no way you can open a database without knowing which kind of DB it is (as you have to know a username/password, and even more: you have to know what arguments are required), so there is no sense in trying to make a virtual pure function out of this.
So, an example of what you could do:
class Database {
public virtual void create(/* ... */) = 0;
// ...
};
class Sqlite3Database : public Database {
Sqlite3Database(string filename);
public virtual void create(/* ... */) override;
// ...
};
class MySqlDatabase : public Database {
MySqlDatabase(int host, short port, string username, string password);
public virtual void create(/* ... */) override;
};

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

c++ Derived class object has no member, why?

I have this problem in my homework.
I have this 2 classes:
-an user class:
class user
{
protected:
int id;
std::string password;
std::string name;
bool online;
static int usersCounter;
static int onlineCounter;
public:
user(std::string = "user", std::string = "1234");
bool connect(std::string);
void disconnect();
void changePassword(std::string);
void changeName(std::string);
virtual void printInfo();
static int getOnlineNo()
{
return onlineCounter;
}
static int getTotalUsers()
{
return usersCounter;
}
friend class admin;
};
and an admin class:
class admin : public user
{
public:
admin(std::string name = "admin", std::string password = "admin"):
user(name, password){}
void disconnectUser(user&);
void viewUsers( user** );
void printInfo() override;
};
When I try to make a polymorphic object and call a function from admin (a function specific for admin, as disconnectUser(...) or viewUsers(...)) I get errors as "class "user" has no member "viewUsers".
user* usr = new admin();
usr->viewUsers(&usr);//error
Is this something usual and I did a wrong design or It should work and I am doing something wrong?
As pointed out in the comment if you define a class of type A you can access only public methods and property of that class.
In your case, viewUsers is present only in the admin class while you're using the generic user class.
You must use inheritance very careful because is very easy to put the wrong methods inside classes or make a wrong inheritance. For example, are you sure the method viewUsers must be inside the admin class? Usually, if a function doesn't depend on the class is best put it outside the class.

Creating new c++ interfaces over old one to add new functions

I am trying to understand if there are best practices around than the one below.
So in our project we had created an interface IForm like below:
class IForm {
protected:
IForm() {}
public:
virtual ~IForm() {}
virtual const std::string& GetId() const = 0;
virtual const std::string& GetTitle() const = 0;
virtual void SetTitle(const std::string& title) = 0;
virtual void SetFormError(const std::string& error_text) = 0;
virtual void ClearFormError() = 0;
};
And then the requirement came to have more functions and therefore we created new interface IForm2:
class IForm2: public IForm {
protected:
IForm2() = default;
public:
virtual ~IForm2() = default;
virtual void RemoveWidget(const std::string &id) = 0;
virtual void Clear() = 0;
};
My question is:
Is there a way around this ? Instead of adding new interface, is there some design pattern that I can use to implement newer requirements rather than adding newer interfaces?
I know the above method works fine. I am just looking for alternatives to implement functionalities.
I've never actually had need of it but you might want to look up the decorator design pattern.
Here's a link to a SO answer about decorators.
Decorator pattern in C++

Aid with code organization?

I have been working on the server code for my game. It works really well, but 90% of the functions are in 1 class.
Usually I find it pretty easy to know how to divide things up. Either each object is a class or each dialog is a class and handles logic for its children.
In this case, the server receives a request, and then either tells the other players or processes and notifies the appropriate players.
Here is the header file:
class ServerCore : public ServerHost, public NetEventListener,
public ServerEventProvider
{
NetEventDecoder m_dec;
NetEventEncoder m_enc;
LoginManager m_login;
ServerPlayerManager m_playerMan;
ServerTableManager m_tableMan;
void sendToTarget();
void sendToAllActive();
void sendToActiveNotTarget();
void sendToTable(int tableNo);
public:
ServerCore();
virtual void onConnect (Lacewing::Server::Client &client);
virtual void onDisconnect (Lacewing::Server::Client &client);
virtual void onError (Lacewing::Error &error);
virtual void onReceive (Lacewing::Server::Client &client, char * data, int size);
virtual void sendChatMessageC(const std::string& message,ChatAreaEnum area);
virtual void requestTableC(int tableNo, int seatNo);
virtual void playerRequestSitC(int tableNumber, int seatNumber);
virtual void playerStoodUpC();
virtual void hostGameC(const SpadesGameInfo& info);
virtual void gameMessageC(SpadesCSMessageEnum message, const std::vector<int>& params);
virtual void modifyListC(const std::string& player, GroupTypeEnum group, bool add);
virtual void canceledHostingRequestC();
virtual void sendInviteC(int tableNo, const std::string& player);
virtual void loginResult(const std::string& name, ServerPlayer* player,
const std::string& sessionID, bool success, bool newSession);
virtual void readyToReceiveLobbyDataC();
virtual void playerAbandonedGameC();
virtual void watchTableC(int tableNo);
virtual void gameCompleted(int tableId);
virtual void playerWantsPlayAgainC();
virtual ~ServerCore(void);
};
}
I do not really know how I could break this down into smaller classes. The tasks they perform are handed to other objects, such as authentication, and data retrieval from database, but all events are currently processed in this 1 file.
The net event decoder calls the appropriate method after converting it from the string received over the wire.
Doing it this way works very well, but the game is going to get bigger and I want to stay clean and modular.
Is this design a good idea? If not, what type of patterns are usually used in game server development to keep things more object oriented?
Thanks
Looking at your class, the command pattern comes to mind. Indeed, the methods ending in C look very much like commands. If you have a command interface:
class Command {
virtual void execute() = 0;
}
and a separate subclass for each command, then the NetEventDecoder could decode the received string into a specific command.
Also, anytime you find yourself passing the same data to multiple methods, that's a hint that there's a class hiding in there. For example, you could pull all the methods taking a tableNumber into a Table class. I would also get rid of the Manager classes and model the associations more directly.
For example:
// A game server contains players and tables
class GameServer {
map<string, Player *> players;
map<int, Table *> tables;
Player *findPlayer(const string &name);
Table *findTable(int tableNumber);
...
}
// A player can perform various actions
class Player {
string name;
bool requestSeat(Table *table);
void standUp();
...
}
// A table maintains the status of seats
class Table {
int tableNumber;
bool requestSeat(int seatNumber);
...
}
The GameServer class above simply models the game and does not deal with networking at all. The NetEventDecoder and ServerCore can then coordinate to provide networking functionality and invoke commands on the GameServer. An example command might look like:
class PlayerStandUpCommand : public Command {
GameServer *server;
string playerName;
void execute() {
Player *player = server->findPlayer(playerName);
player->standUp();
}
}

Export a class with std::string

I know this subject has been covered and re-talked, but I still get stuck every time I need to do something like that, and the internet is full of different answers.
so I decided to simply ask how to deal with such situation once and for all.
Lets say I have the following class:
class PETS_EXPORT_API dog
{
public:
dog(std::string name):_name(name){}
~dog(){}
private:
std::string _name;
};
Obviously this code would generate a warning because I'm trying to export std::string. How do I solve such issue ?
thanks!
Alternative to Joe McGrath's answer:
If you really want your clients to have access to Dog public & protected interface, and does not make sense to have an abstract interface,
You could use the pImpl idiom, to hide the private interface.
Additionally you could export the string in the form of chars
Hide your original dog:
class Dog_Impl // your original class
{
public:
Dog_Impl(std::string name):_name(name){}
~Dog_Impl(){}
string::get_name();
private:
std::string _name;
};
Put this into your API:
class Dog_Impl; // fwd declaration
class PETS_EXPORT_API Dog {
public:
Dog(const char *name);
~Dog();
const char *get_name();
private:
Dog_Impl *pImpl;
};
The implementation should simply pass all public & protected interface to the pImpl:
Dog::Dog(const char *name)
{
pImpl = new Dog_Impl(name);
}
Dog::~Dog()
{
delete pImpl;
}
const char *Dog::get_name()
{
return pImpl->get_name().c_str();
}
You don't want to export the private members. Only the public interface. Make an abstract base class and export it.
struct DogInterface
{
virtual string IAmADog(void) = 0; // your public interface goes here
};
// Factory function that creates dogs
extern "C" PETS_EXPORT_API DogInterface* APIENTRY GetDog();
If you just want to export the string for access
__declspec(dllexport) const char* MyExportedString()
{
return myString.c_str()
}