C++ Design pattern for separate accessor/mutator interfaces - c++

I have a data structure "Person"
struct Person
{
protected:
string name;
int age;
string address;
...
}
I want to create "views" around this structure to separate out access to different member variables:
class PersonRead: public Person
{
public:
string getName() {..}
int getAge() {...}
...
}
class PersonUpdate: public Person
{
public:
void setAddress( string address_ ) {...}
void setAge( int age_ ) {...}
...
}
I use this to only expose those methods/variables which are really required:
int main()
{
...
writePersonDataToFile ( (PersonRead) personObj );
updatePersonData ( (PersonUpdate) personObj);
...
}
Though the above code serves my purpose, there are several issues including:
The public inheritence here is not exactly an 'is-a' relationship
I need to derive IndianPerson from Person, and all the corresponding interfaces. This leads to bad diamond pattern:
struct IndianPerson: public Person {};
class IndianPersonRead: public IndianPerson, public PersonRead {}; //Person Class common, Diamond pattern here!
Is there a name for such a design pattern? What are better ways to implement this pattern? I have a feeling Policy classes might help, but cant figure out how to implement this
Any examples would be great help

For your scenario this might seem like overkill but, if you want fine grained control over which classes can call different methods on your class the c++ client-attorney idiom idiom might be appropriate.
For a detailed description of this idiom see http://drdobbs.com/184402053
Here is a rough example (note: this has not been compiled, although it is based on production code I am currently using):
class Person
{
public:
/// constructor destructor etc:
private:
string getName() { return name; }
public:
/// Writer Attourney that access to allows class PersonReader access
/// to getXXX functions
class ReaderAttorney
{
private:
/// Add additional reader member functions...
static string readName( Person& p )
{
return p.getName();
}
// Make any classes that shuold be allowde read access friends of the
// attorney here
friend class PersonReader;
};
/// Writer Attourney that access to allows class PersonWriter access
/// to setXXX functions
class WriterAttorney
{
private:
/// Add additiona reader member functions...
static string setName( Person& p, const string& newName )
{
p.setName( newName );
}
friend class PersonWriter;
};
private:
string name;
int age;
string address;
};
This can be used as follows:
void PersonWriter::setPersonDetails( const string& name, int age .... )
{
// PersonWriter is a frend of WriterAttorney and is granted access
Person::WriterAttorney::setName( name );
Person::WriterAttorney::setName( age );
// Note this will fail, since PersonWriter is not a friend of
// ReaderAttorney, ergo it is not granted read permission:
Person::ReaderAttorney::readName();
}

I think that your approach is not correct at all: PersonRead and PersonUpdate are not Persons. They read and modify Person data but are not really Person.
In the same way, IndianPersonRead and IndianPersonUpdate are not an IndianPerson.
I separate this relationship in following:
PersonRead use Person
PersonUpdate use Person
IndianPerson inherits from Person: is a Person
IndianPersonRead inherits from PersonRead and use IndianPerson
IndianPersonUpdate inherits from PersonUpdate and use IndianPerson
I show an example of my apporach:
#include <string>
#include <iostream>
using namespace std;
struct Person
{
string getname() const { return name; }
string getaddress() const { return address; }
void setaddress(const string & address_) { address = address_; }
void setname(const string & name_) { name = name_; }
protected:
string name;
int age;
string address;
};
class PersonRead
{
public:
string getname(const Person & p) { return p.getname(); }
};
class PersonUpdate
{
public:
void setAddress(Person & p, const string & address_ ) {p.setaddress(address_); }
void setname(Person & p, const string & name_ ) {p.setname(name_); }
};
struct IndianPerson : public Person
{
string gettribe() const { return tribe; }
void settribe(const string & tribe_) { tribe = tribe_; }
protected:
string tribe;
};
struct IndianPersonRead : public PersonRead
{
public:
string gettribe(const IndianPerson & p) const { return p.gettribe(); }
};
struct IndianPersonUpdate : public PersonUpdate
{
public:
void settribe(IndianPerson & p, const string & t) { p.settribe(t); }
};
int main(int argc, char **argv)
{
IndianPerson ip;
IndianPersonUpdate ipU;
IndianPersonRead ipR;
ipU.settribe(ip, "Cheroki");
ipU.setname(ip, "Charly");
cout << ipR.getname(ip) << " : " << ipR.gettribe(ip) << endl;
}

First of all I will agree with the Tio's point of view PersonUpdate is not a Person so there is a wrong inheritance usage. Also I believe that you need to make your classes with target to represent the real world so classes like PersonUpdate are wrong because they represent the action and not the object.
In your case one solution could be to use the visitor design pattern, so the Person could accept a especially designed IPersonStream interface in order to perform the serialization in classes which will implement this interface.
Person stream will accept the persons attributes on it or for good the Person's memento take a look on memento design pattern, and serialize it to xml or whatever you want.

I don't have a design pattern name, but to resolve your concerns, I would swap the inheritance relation and let Person inherit from the PersonReader and PersonWriter interfaces. This way, objects that must only read from Person use the PersonReader interface and as such promises to not change it.
By making every member of Person private, you can even make sure that Person is not accessed in another way, but then every class that inherits from Person should have these members private.

Related

Subclass as argument in superclass's member function, C++

I'm new to OOP and I'm working on a C++ project. I isolated my problem to make answering easy but here's the real scenario:
I have a superclass member function, that modifies values inside the object that called it. The modification is based on a value coming from another object of the same class. This object is given to the function as the only parameter. Such as:
void BaseClass::function(BaseClass x) {}
However, I created a subclass. And if the parameter is a subclass type, I want to modify its unique attribute, too.
void BaseClass::function(DerivedClass x) {}
The problem is that the subclass is obviously defined later in the code.
I don't want it as two separate methods, because the calculation algorithm is already written inside, and also the solution I search for doesn't require to change the code at the places where the function is already in use. Besides, every other possibility that comes to mind (e.g. using typeid()) looks silly.
#include <iostream>
#include <string>
class Base
{
protected:
//common attribute
const std::string name;
public:
//constructor for common attribute
Base(const std::string nameString) : name(nameString) {}
//getter
std::string getName() { return name; }
//superclass as parameter
void test1(Base &example) { std::cout << example.getName(); }
//subclass as parameter (I'd want the line below to work)
//void test2(Derived &example) { std::cout << example.getNumber(); }
};
class Derived : private Base
{
protected:
//unique attribute
const std::string number;
public:
//constructor
Derived(const std::string nameString, const std::string numberString) : Base(nameString),
number(numberString) {}
//getter for unique attribute
std::string getNumber() { return number; }
};
int main ()
{
Base object = Base("whatever");
Base baseParameter = Base("base");
Derived derivedParameter = Derived("derived", "12");
object.test1(baseParameter);
//object.test2(derivedParameter);
return 0;
}
What is the standard way of doing it?
You could make test2 a template, and ensure that it's only used with types derived from Base:
template<typename Derived>
void test2(Derived &example)
{
static_assert(std::is_base_of_v<Base, Derived>);
std::cout << example.getNumber();
}
Here's a demo.

Is there a way in C++ to restrict a function of a given class to another class only(without using inheritance, friend)?

I want to design a class having a function which should be restricted to be called from another class only. Specifically, in the given code
class Club
{
int id;
string name;
vector<string> members;
int generateId()
{
static int i=1;
return i++;
}
public:
Club(string name) { this->name = name; this->id = generateId(); }
void registerMember(string memberName) { members.push_back(memberName); }
int getId() { return id; }
};
class Application
{
vector<Club> clubs;
public:
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
}
};
An user(public user) can create an object of the class Club and register using the function registerMember() since it's public. I want the user to register via an object of the class Application, using the addMemberToClub() function only. If the user goes by the former way mentioned, I can't keep track of the user. Is there a way to enforce the latter?
I don't want to use the access modifier protected since inheritance has no meaning here.
I don't want to use the friend keyword, since it's considered bad practice.
Here is a "lock-and-key" way to permit another class (and only that class) or even a single function in another class to access just one member function, unlike friend which exposes all private members at the same time:
#include <iostream>
class Key;
class Locked
{
static const char* const Greeting;
public:
static Key secretive();
static void attacker();
};
struct Admin
{
void doit();
};
class Key
{
~Key() = default;
//friend class Admin;
friend void Admin::doit();
friend Key Locked::secretive();
};
void Admin::doit()
{
Locked::secretive();
std::cout << Locked::Greeting; // compile error
}
constexpr const char* Locked::Greeting = "Hello!\n";
Key Locked::secretive()
{
std::cout << Greeting;
return Key();
}
void Locked::attacker()
{
std::cout << Locked::Greeting; // ok, it's just private
Locked::secretive(); // compile error, it's locked down tight
}
int main()
{
Admin a;
a.doit();
std::cout << Locked::Greeting; // compile error
Locked::secretive(); // compile error
}
It also works around the "which class is declared first?" problem that prevents two classes from mutually friending individual member functions of each other, because the restricted operation needs to follow only a forward declaration of the key type; the full definition of the other type can (and in this example does) appear above the key definition, allowing individual members to be named in the key type's friend directive.
Note that in this solution the "obvious" fact that other members of the same class can access the locked function is NOT true. The compiler prevents Locked::attacker() from calling Locked::secretive().
Note also that I've used static in this example to minimize the number of objects I had to create, but the approach works just fine for non-static member functions too.
A potentially MUCH easier way to restrict what part of the program can call your protected function is with a simple flag:
class Application
{
static bool addingMember = 0;
public:
static bool isRegistrationOk() { return addingMember; }
void registerClub(Club &club) { clubs.push_back(club); }
void addMemberToClub(int clubId, string memberName)
{
addingMember = true;
for(Club club: clubs)
{
if(clubId == club.getId())
club.registerMember(memberName);
}
addingMember = false;
}
};
void Club::registerMember(string memberName)
{
assert(Application::isRegistrationOk());
members.push_back(memberName);
}
Much easier to grok, but it's a runtime check not compile-time, and requires additional work to be made thread-safe. But it accomplishes the goal with no usage of friend or inheritance.
friend is an appropriate mechanism to use in this case. Make registerMember private in Club, and Club can grant friendship to Application:
class Club
{
// ...
void registerMember(string memberName) { members.push_back(memberName); }
public:
// ...
friend class Application;
};
Now only Application can call registerMember, and Club as well, of course.
Here's a demo.

how to create a class from an identifier?

the title might be a bit misleading, but I want to give some instance of a class an instance of a different class through polymorphism. I think that may have been even more misleading so I'll give an example;
Say I have a class called Spell, that is a parent class to the class Firebolt. I want another class, say Character, to be able to have the spell, 'Firebolt', in an its memory without ever having to #include the files for 'Firebolt'.
Now, I can think of a way that prior games have done this before. By giving each spell (or whatever else specific class type) a static const string ID or name and in spell having some function that can access this ID/name and return a new Firebolt() if they are the same.
This sounds pretty good actually, the problem I'm having is I don't know how to code this. I'm not sure how I can access these ID's from the parent class, and I'm not sure how to make a virtual function that will actually return the correct Spell. Any help would be amazing. I'll also provide the actual class code I'm working with here in case it might help you guys to answer, or someone with a similar problem to solve it.
The parent class;
class Art {
std::string name;
int EPCost;
int castTime;
int AoESize;
public:
Art(std::string n, int cp, int ct, int as):name(n), EPCost(cp), castTime(ct), AoESize(as) {}
virtual ~Art() {}
static Art* findArt(std::string ID);
int getAoESize() {return AoESize;}
std::string getName() {return name;}
int getEPCost() {return EPCost;}
virtual int getBaseDamage() = 0;
};
The subclass;
class FireBolt:public Art {
static const std::string name;
static const int EPCost;
static const int castTime;
static const int AoESize;
static const std::string ID;
public:
FireBolt():Art(name, EPCost, castTime, AoESize) {}
~FireBolt() {}
int getBaseDamage();
};
All you need to do is make your FireBolt::ID public.
class FireBolt:public Art {
public:
static const std::string ID;
...
};
Art* Art::findArt(const std::string& ID)
{
if (ID == FireBolt::ID)
return new FireBolt(...);
...
}

How to initialize grandparent's (const) property in grandchild in C++?

I know this might look like a trivial question, but I haven't found really an elegant C++ solution to the following problem.
I want to represent a complex (tree-like) hierarchy of a "world" of objects. Let's say Animals. Every animal has some basic const properties.
Like for example a name. Then it also has some methods, but they are not significant for this problem.
class Animal {
public:
const char *GetName() const;
protected:
const char *name;
};
class Insect : public Animal {
...
};
class Butterfly : public Insect {
...
};
In this hierarchy I would like to initialize the name in every derived (grand)child. What is an elegant solution to this?
It is also important to say that in this "world" there be only instances of the tree leaves. That is, there will be no objects "Animal" or "Insect". But there will be objects "Butterfly", "Bee" or "Mosquito".
I know the "standard" way to do this is to put name into constructor:
Animal::Animal(const char *name) : name(name) {}
Insect::Insect(const char *name) : Animal(name) {}
Butterfly::Butterfly() : Insect("Butterfly") {}
But if there are more of these properties, the derived classes need also some initialization and the hierarchy has more levels it can become quite a mess:
Animal::Animal(const char *name) : name(name) {}
Vertebrate::Vertebrate(const char *name) : Animal(name) {}
Mammals::Mammals(const char *name) : Vertebrate(name) {}
Ungulate::Ungulate(const char *name) : Mammals(name) {}
Horse::Horse() : Ungulate("Horse") {}
Another option I can see is to drop the const and assign directly in the grandchild's constructor:
class Animal {
public:
const char *GetName() const;
protected:
std::string name;
};
Horse::Horse() {this->name = "Horse";}
But that is also not optimal, because the const is lost and it is more prone to errors (the initialization can be forgotten).
Is there some better way to do this?
Hm - hope that I get not locked out from SO for that answer, but you could use a virtual base class that implements the name-property. Thereby, you will not have to propagate initialization in a base class all way through the hierarchy but could directly address the "very base" constructor with the name-property. Furthermore, you will actually be enforced to call it in any "Grandchild"-class, so you can't forget it by accident:
class NamedItem {
public:
NamedItem(const char* _name) : name(_name) {}
const char *GetName() const;
protected:
const char *name;
};
class Animal : public virtual NamedItem {
public:
Animal(int mySpecificOne) : NamedItem("") {}
};
class Insect : public Animal {
public:
Insect(int mySpecificOne) : Animal(mySpecificOne), NamedItem("") {}
};
class Butterfly : public Insect {
};
The elegant solution is to pass arguments through initialisation. For example, if the "name" variable was the name of the Butterfly (such as "sally" or "david") then it would be obvious it has to be done through initialisation. If you are finding that is ugly, as it is here, it may indicate that your data decomposition/class heirarchy are at fault. In your example every Butterfly object would have an identical set of properties that really refer to their class rather than each instance, ie they are class variables not instance variables. This implies that the "Butterfly" class should have a static pointer to a common "Insect_Impl" object (which might have a pointer to a single "Animal_Impl" object etc) or a set of overridden virtual functions. (Below I only show one level of heirarchy but you should be able to work out more levels)
// Make virtual inherited functionality pure virtual
class Animal {
private:
std::string objName; // Per object instance data
public:
virtual ~Animal(std::string n): objName(n) {}
virtual std::string const& getName() = 0; // Per sub-class data access
virtual std::string const& getOrder() = 0; // Per sub-class data access
std::string const& getObjName() { return this->objName; }
};
// Put common data into a non-inherited class
class Animal_Impl{
private:
std::string name;
public:
Animal_Impl(std::string n): name(n);
std::string const& getName() const { return this->name; }
};
// Inherit for per-instance functionality, containment for per-class data.
class Butterfly: public Animal{
private:
static std::unique< Animal_Impl > insect; // sub-class data
public:
Butterfly(std::string n): Animal(n) {}
virtual ~Butterfly() {}
virtual std::string const& getName() override {
return this->insect->getName(); }
virtual std::string const& getOrder() override {
static std::string order( "Lepidoptera" );
return order; }
};
// Class specific data is now initialised once in an implementation file.
std::unique< Animal_Impl > Butterfly::insect( new Animal_Impl("Butterfly") );
Now using the Butterfly class only needs per-instance data.
Butterfly b( "sally" );
std::cout << b.getName() << " (Order " << b.getOrder()
<< ") is called " << b.getObjName() << "\n";
The issue with your alternative, or any alternative leaving name non-const and protected, is that there is no guarantee that this property is going to be setup properly by the subclasses.
What does the following class give you ?
class Animal {
public:
Animal(const char* something)
const char *GetName() const;
private:
const char *name;
};
The guarantee of the immutability of the Animal interface, which can be a big plus when doing multithreading. If an object is immutable, multiple threads can use it without being a critical resource.
I know the "standard" way to do this is to put name into constructor:
... But if there are more of these properties, the derived classes
need also some initialisation and the hierarchy has more levels it can
become quite a mess
It is not messy at all. Given that there is only one place where the members of object A are being initialised, and it is within the constructor of their subclasses.

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()
}