C++ Builder Pattern with Inheritance - c++

I have a class I would like to use the builder pattern on, but it is derived from a base class whose attributes I need to access. I can't access the members of BaseClass in my implementation without making them public, even if I derive Builder from BaseClass or something equally smelly. My classes:
BaseClass.h:
class BaseClass
{
protected:
CString name;
}
DerivedClass.h:
class DerivedClass : public BaseClass
{
public:
// builder starts here and has the same base class as the class it is nested in
// (if it doesn't, we can't get access to name)
static class Builder : public BaseClass
{
public:
Builder::Builder(CString pName)
{
this->name = pName;
}
Builder Builder::Description(CString pDescription)
{
this->description = pDescription;
return *this;
}
};
public:
CString description;
};
DerivedClass.cpp:
DerivedClass::DerivedClass(Builder builder)
{
this->name = builder.name; // this is NOT ok
this->description = builder.description; // this is ok
}
My problem is that I can't access builder.name. Visual Studio says that "protected member BaseClass::name is not accessible through a DerivedClass::Builder pointer or object". I've tried fiddling around with making Builder a friend of BaseClass, but to no avail. This post has also provided a workaround, but it's for Java, and very messy.
Is there a decent way to use the builder pattern with inheritance in C++?

Even though Builder is declared inside of DerivedClass, Builder is not implicitly friends with DerivedClass, like you are expecting. Builder is still its own class, and it follows the same rules as any other class, including scope access rules. That is why DerivedClass cannot access protected members of Builder by default. You need to explicitly declare that friendship.
Also, your Builder::Description() method will not work as-is because Builder does not have a description member. The this pointer inside of Builder methods still refers to the Builder instance, not a DerivedClass instance. If you want the Builder to access members of DerivedClass, it needs to be given a pointer to a DerivedClass instance. Otherwise, give Builder its own description member (which it looks like you were attempting to do anyway).
Try this:
BaseClass.h:
class BaseClass
{
protected:
CString name;
};
DerivedClass.h:
class DerivedClass : public BaseClass
{
public:
class Builder : public BaseClass
{
public:
Builder(const CString &pName)
{
this->name = pName;
}
Builder& Description(const CString &pDescription)
{
this->description = pDescription;
return *this;
}
public:
CString description; // <-- add this
friend class DerivedClass; // <-- add this
};
public:
DerivedClass(const Builder &builder);
public:
CString description;
};
DerivedClass.cpp:
DerivedClass::DerivedClass(const DerivedClass::Builder &builder)
{
this->name = builder.name; // this is ok now
this->description = builder.description; // this is ok now
}

Don't attempt to access the member directly. Use a public accessor method.

Related

Setting value from Derivered class, while accesing same value from base class

I am getting an issue for retrieving BaseClass correct enum value.
class BaseClass
{
public:
enum EntityId {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
void setEntityId(EntityId id) { _Entityid = id; }
EntityId getEntityId() { return _Entityid; }
protected:
EntityId _Entityid;
};
and
class DeriveredClassA : public SomeClass, public BaseClass {....};
class DeriveredClassB : public SomeClass, public BaseClass {....};
The initialization goes like this
DeriveredClassA->setEntityId(BaseClass::EntityId::EN_PLAYER);
DeriveredClassB->setEntityId(BaseClass::EntityId::EN_OBSTACLE);
Which is placed into a different vector list correspoinding to that enum.
However, I am forced to use void* to do static_casts cats...
Like this:
BaseClass* EA = static_cast<BaseClass*>(bodyUserDataA); //bodyUserDataA and bodyUserDataB are both void*
BaseClass* EB = static_cast<BaseClass*>(bodyUserDataB);
And I am trying to retrieve using EA->getEntityId() and EB->getEntityId() so I could check which one is EN_PLAYER, which one is EN_GROUND and etc. So then I could up-class from base into derivered class and do other stuff with it.
Tried using with virtual, however somehow I am receiving 2 copies of _EntityID, which can be either the same or DIFFERENT between my Derivered and BaseClass of that one object.
Moreover, I can't cast right away into DeriveredClass, since the code checking would be huge, due to many different types of DeriveredClass'es (DeriveredClassA, DeriveredClassB, DeriveredClassC, DeriveredClassD) with their corresponding vector list.
My question is that How I need setup correctly both Base and Derivered class, so that I could access _EntityID from Baseclass which is the same of that DeriveredClass? My main problem might is that I used incorectly virtual functions, so I left on default to understand my issue.
P.S. This is mainly my c++ issue, other tags are added due to I am using game engine and physics engine for this case.
I believe that you want your code to look more like this:
class Entity
{
public:
enum Type {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
Type getType() { return _type; }
protected:
Entity(Type type): _type(type) {}
private:
const Type _type;
};
Then your derived classes and usage of this base would be more like:
class PlayerEntity: public Entity, public SomeClass
{
public:
PlayerEntity(std::string name): Entity(EN_PLAYER), _name(name) {}
std::string getName() const { return _name; }
private:
std::string _name;
};
class PlatformEntity: public Entity, public SomeClass
{
public:
PlatformEntity(): Entity(EN_PLATFORM) {}
};
Initialization is then done like:
int main()
{
PlatformEntity platform;
std::vector<PlatformEntity> platforms(platform);
std::vector<PlayerEntity> players;
players.emplace_back("Bob");
players.emplace_back("Alice");
players.emplace_back("Ook");
}
Access from user-data could then look like this:
// bodyUserDataA and bodyUserDataB are both void*
Entity* const EA = static_cast<Entity*>(bodyUserDataA);
Entity* const EB = static_cast<Entity*>(bodyUserDataB);
switch (EA->getType())
{
case Entity::EN_PLAYER:
{
PlayerEntity* player = static_cast<PlayerEntity*>(EA);
std::cout << "Found player: " << player->getName();
break;
}
case Entity::EN_OTHER:
...
default:
break;
}

C++: how to make a group of derived classes be able to access private members of one class?

Suppose a class: Library
And we have a group of derived class from the base class LibraryCustomer, such as:
Kid, Parent, Student,
etc
In the class of Library, there are a group of (tons of) private members variables.
Since there are tons of private members in the class of Library, I do not want to use getter and setter which are tedious.
Plus the LibraryCustomer derived classes will often refer to those members. Getter and Setter are not convenient.
In order for those LibraryCustomers to access those private member in Library,
I need to claim those LibraryCustomers as friend classes in Library.
But since the derived classes keep growing, I do not want to add them one by one in the class Library.
Add the base class LibraryCustomer as friend in Library seems not to work.
So what is another better way?
[Update] I want to access tons of private member variables in the class of Library.
Since there are many, so I do not want to use getter and setter.
I hope the derived classes from LibraryCustomer can freely access those private member variables in the class of Library.
Provide a function in LibraryCustomer that accesses Library to get the data and provides that data to the classes derived from LibraryCustomer.
class Library
{
friend class LibraryCustomer;
private:
std::string name;
};
class LibraryCustomer
{
protected:
std::string getLibraryName(Library const& lib)
{
return lib.name;
}
};
class Kid : public LibraryCustomer
{
// Can use LibraryCustomer::getLibraryName() any where
// it needs to.
};
Having said that, it will be easier to provide access to the data from Library itself.
class Library
{
public:
std::string getName() const { return name; }
private:
std::string name;
};
Then, there won't be the need for the friend declaration and the wrapper function LibraryCustomer::getLibraryName().
EDIT
#MooingDuck has interesting suggestion. If you have to expose many such variables, it might be better to put them all in one class. Working code at http://coliru.stacked-crooked.com/a/2d647c3d290604e9.
#include <iostream>
#include <string>
class LibraryInterface {
public:
std::string name;
std::string name1;
std::string name2;
std::string name3;
std::string name4;
std::string name5;
std::string name6;
};
class Library : private LibraryInterface
{
public:
Library() {name="BOB";}
private:
LibraryInterface* getLibraryInterface() {return this;} //only LibraryCustomer can aquire the interface pointer
friend class LibraryCustomer;
};
class LibraryCustomer
{
protected:
LibraryInterface* getLibraryInterface(Library& lib) {return lib.getLibraryInterface();} //only things deriving from LibraryCustomer can aquire the interface pointer
};
class Kid : public LibraryCustomer
{
public:
void function(Library& lib) {
LibraryInterface* interface = getLibraryInterface(lib);
std::cout << interface->name;
}
};
int main() {
Library lib;
Kid k;
k.function(lib);
}

Implement possibility to access class member static as well as non-static on a derived class

I have the following classes.
// My baseclass
class Item {
public:
virtual const std::string GetItemName() = 0;
};
// My derived class
class Shovel : public Item {
private:
static const std::string _ITEM_NAME = "tool_shovel";
public:
const std::string GetItemName(){
return _ITEM_NAME;
}
}
With this i can access the names of my Item objects like this:
Item* myItem = new Shovel();
myItem.GetItemName(); // Returns "tool_shovel" ofcourse
I would now also like to access the name of an item without having an instance of it like this.
Shovel::GetItemName();
I know it is not possible to implement a virtual static function.
but is there any way to implement this in a 'nice' way or is this more a problem in my concept?
Thanks for the help!
I didn't know it is possible to call a static function directly from an instance, so i solved my problem now with 2 methods.
One public static function, so i can get the name of an item at any time. And another private non-static function to let the baseclass get the name of the current item.
Here is the code:
// My baseclass
class Item {
protected:
virtual const std::string _GetItemName() = 0;
};
// My derived class
class Shovel : public Item {
private:
static const std::string _ITEM_NAME = "tool_shovel";
protected:
const std::string _GetItemName(){
return _ITEM_NAME;
}
public:
static const std::string GetItemName(){
return _ITEM_NAME;
}
};
I hope this helps anyone. If you have questions feel free to ask.

Polymorphic subtyping in C++

I'm quite new to C++, and I need a clarify porting a project from Java.
In Java I can declare a base class and its derived, with generics, in this way:
public class GenericHost{
public enum HostType{
server,
client
}
public HostType type_;
}
public class MyClient extends GenericHost{
public String clientName;
}
public class MyServer extends GenericHost{
public String serverName;
}
public abstract class GenericNetwork<hostType extends GenericHost> {
public enum NetworkType{
central,
peripheral
}
private NetworkType type_;
protected hostType masterHost;
public hostType getMasterHost(){
return masterHost;
}
public abstract String getName();
}
public class CentralNetwork extends GenericNetwork<MyServer>{
#Override
public String getName(){
return masterHost.serverName;
}
}
public class PeripheralNetwork extends GenericNetwork<MyClient>{
#Override
public String getName(){
return masterHost.clientName;
}
}
This allows me to:
In derived classes I'm allowed to use methods and variables of specified derived class (e.g. serverName / clientName in CentralNetwork / PeripheralNetwork) and not only of the base class
Derived class is tiped, so the compiler / editor can suggest me every method & variable during code editing
I'm forced to use a class that is derived from the base class (GenericNetwork / GenericHost), every error is at compile time and not run time
Every method / variable that use generics will be treated in derived class as the child class and not the base class (e.g. in CentralNetwork, the getMasterHost will return the derived MyServer, not the base GenericHost).
I wish to know if does exist anything similar in C++.
I already looked for templates, inheritance and subtyping but I can't find a way to do something smarter like I did in Java. I hope I missed something...
EDIT:
This what I tried in C++:
class GenericHost{
public enum HostType{
server,
client
}
public HostType type_;
}
class MyClient : public GenericHost{
public String clientName;
}
class MyServer : public GenericHost{
public String serverName;
}
template<class hostType : GenericHost> <--WISH, forced base class
class GenericNetwork {
public enum NetworkType{
central,
peripheral
}
private NetworkType type_;
protected hostType masterHost;
public hostType getMasterHost(){
return masterHost; <--WISH, should return MyServer / Myclient in derived class
}
public virtual std::string getName();
}
class CentralNetwork<MyServer> : public GenericNetwork{
public std::string getName(){
return masterHost.serverName; <--WISH, tiped and suggested by editor / compiler
}
}
class PeripheralNetwork<MyClient>: public GenericNetwork{
public std::string getName(){
return masterHost.clientName; <--WISH, tiped and suggested by editor / compiler
}
}
I don't have the C project with me now, so I rewrote it on the fly, sorry for any mistake...
As far as I know there's no explicit feature that lets you do this. You can use static_cast though, which will give you a compile time error if the types are not compatible.
template <class hostType>
class GenericNetwork {
public:
GenericNetwork() {
static_cast<GenericHost*>((hostType*)nullptr); // or 0 or NULL if not C++11
}
};
If hostType and GenericHost are compatible, the cast will succeed but do nothing. Otherwise, you'll get a compile time error.
There's no dedicated feature to explicitly constrain template arguments (*), but you can use (C++11's)
static_assert( std::is_base_of<GenericHost, hostType>::value,
"The template argument must be derived from GenericHost" );
(*) There'll be template constraints hopefully in C++17.
This is a compile-time assertion and can be used as a declaration:
template<class hostType>
class GenericNetwork {
static_assert( std::is_base_of<GenericHost, hostType>::value,
"The template argument must be derived from GenericHost" );
public:
enum NetworkType{
central,
peripheral
}
virtual ~GenericNetwork(); // you typically want a virtual dtor in an ABC
hostType& getMasterHost(){ // you might want to return a (const) reference
return masterHost;
}
virtual std::string getName() = 0; // abstract
private:
NetworkType type_;
hostType masterHost; // or protected
// consider making the copy ctor and copy assignment op protected
// to prevent unintended slicing
}
As everybody points out, C++ templates can implement this so it doesn't merit dedicated syntax.
Here's a rather literal translation that enforces the baseclass requirement by simply doing it.
#include <string>
struct GenericHost {
enum HostType { server,client } type_;
};
template<class GenericHost=GenericHost>
struct MyClient : GenericHost { std::string clientName; };
template<class GenericHost=GenericHost>
struct MyServer : GenericHost { std::string serverName; };
template< template<class> class SpecificHost, class GenericHost=GenericHost >
struct GenericNetwork
{
typedef SpecificHost<GenericHost> hostType;
virtual ~GenericNetwork() { };
enum NetworkType { central, peripheral };
hostType getMasterHost() { return masterHost; }
virtual std::string getName() = 0;
protected: hostType masterHost;
private: NetworkType type_;
};
struct CentralNetwork : GenericNetwork<MyServer> {
std::string getName() { return masterHost.serverName; }
};
struct PeripheralNetwork : GenericNetwork<MyClient> {
std::string getName() { return masterHost.clientName; }
};
// testing: force instantiation:
struct CentralNetwork makeme;
struct PeripheralNetwork metoo;
std::string doit() { return makeme.getName() + metoo.getName(); }
I believe this gets all four desiderata, though the errors would be detected in different places. As others point out static_cast<requiredBase*>((testedClass*)0); can do that job, but bypassing the protection takes work, not just a mistake, and it would show up in the type system so I don't see the point.
(edit: add the virtual destructor, no dessert for me tonight. Bad dog.)

access protected variable - complicated situation with inheritance and sub-classes

Hmm... I'm trying to break down my problem...
There is a library with some classes that do almost what I want. I can't change classes of the library so I want to derive them and change what I need.
In this case there is a derived class in the library with two subclasses. Now I derive the class and the subclasses.
In the second sub-class there is a virtual method witch modifies a protected variable from the first sub-class.
I want to override the virtual method with a new virtual method which calls the old virtual wethod an then modify the protected variable again.
Why am I getting the error in mySubClass2 while accessing fResponse?
How can I solve my problem?
class libraryClass : pulic someLibraryBaseClass {
protected:
libraryClass::librarySubClass2 lookUpFunction(int ID) {
//some magic to find the obj
return obj;
}
public:
class librarySubClass2;
class librarySubClass1 {
public:
librarySubClass1(libraryClass baseObj) {
myBaseObj = baseObj;
}
void someCallingFunction(int ID) {
libraryClass::librarySubClass2 obj = myBaseObj->lookUpFunction(ID)
obj->someHandleFunction(this)
cout << fResponse;
}
protected:
friend class librarySubClass2;
unsigned char fResponse[200];
private:
libraryClass myBaseObj;
};
class librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
snprintf((char*)obj->fResponse, sizeof obj->fResponse, "Some Text...\r\n"
}
};
};
class myDerivedClass : public libraryClass {
public:
class mySubClass2 : public libraryClass::librarySubClass2;
class mySubClass1 : public libraryClass::librarySubClass1 {
protected:
friend class mySubClass2;
};
class mySubClass2 : public libraryClass::librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
libraryClass:librarySubClass2::someHandleFuntion(obj);
snprintf((char*)obj->fResponse, sizeof obj->fResponse, "Add some more Text...\r\n"
}
};
};
Edit: Forgot * in Method of mySubClass2
Possible solution:
class mySubClass2 : public libraryClass::librarySubClass2 {
protected:
virtual void someHandleFunction(libraryClass::librarySubClass1* obj) {
libraryClass:librarySubClass2::someHandleFuntion(obj);
myDerivedClass::mySubClass1* nowMyObj = (myDerivedClass::mySubClass*) obj;
snprintf((char*)nowMyObj->fResponse, sizeof nowMyObj->fResponse, "Add some more Text...\r\n"
}
};
Now I derive the class and the subclasses.
In your example code, you're only deriving the main class and not the subclass. You have to inherit also the subclass:
class libraryClass : pulic someLibraryBaseClass
{
class librarySubClass1 : public someLibraryBaseClass::someLibrarySubClass1 { };
// ....
};
But that can be done only if the subclass is accessible (protected/public).
As far as I can tell you wonder why you can't access obj->fResponse in
void mySubClass2::someHandleFunction(libraryClass::librarySubClass1 obj) { ... }
Well, obj is of type librarySubClass1 which inherits its share of fResponse from the common ancestor. However, that is the share of a relative of mySubClass2, not yours as you are mySubClass2! You can only access the fResponse member of objects which are known to be of type mySubClass which actually happens to be known to be not the case for a librarySubClass1 object.
Getting access to librarySubClass::fResponse is as if you got free access to your uncle's inheritance from your grandparents. Unless you have a very unusual family sharing its wealth freely among all family members, you probably won't have access to your uncle's inheritance either.
Because fResponse in mySubClass2 is treated as protected and at that point it is outside of libraryClass, it only worked on librarySubClass2 because it is inside libraryClass.