Polymorphic subtyping in C++ - 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.)

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;
}

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.

C++ Builder Pattern with Inheritance

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.

inherited function inaccessable in C++

I am writing a small program in Visual C++ 2010.
This is code of the base class:
class BaseInfo {
private:
std::map <std::string, std::string> info;
std::vector<std::string> extra_info_key;
public:
uint get_id ();
//Other function is hidden
};
uint BaseInfo::get_id () {
return (uint)atoi ((info["ID"]).c_str());
}
Then I make a derived class, which is announced as:
class test:BaseInfo {
public:
void f();
};
void test::f (test& inf) {
cout<<inf.get_id()<<endl;
}
But I got an error:
function "BaseInfo::get_id is inaccessible.
I am confused, it seems all is in the c++ rules.
You're using private inheritance, that's why.
Change:
class test : BaseInfo
to:
class test : public BaseInfo
For more info about public, protected and private inheritance, look here

How to declare factory-like method in base class?

I'm looking for solution of C++ class design problem. What I'm trying to achieve is having static method method in base class, which would return instances of objects of descendant types. The point is, some of them should be singletons. I'm writing it in VCL so there is possibility of using __properties, but I'd prefer pure C++ solutions.
class Base {
private:
static Base *Instance;
public:
static Base *New(void);
virtual bool isSingleton(void) = 0;
}
Base::Instance = NULL;
class First : public Base { // singleton descendant
public:
bool isSingleton(void) { return true; }
}
class Second : public Base { // normal descendant
public:
bool isSingleton(void) { return false; }
}
Base *Base::New(void) {
if (isSingleton())
if (Instance != NULL)
return Instance = new /* descendant constructor */;
else
return Instance;
else
return new /* descendant constructor */;
}
Arising problems:
how to declare static variable Instance, so it would be static in descendant classes
how to call descendant constructors in base class
I reckon it might be impossible to overcome these problems the way I planned it. If so, I'd like some advice on how to solve it in any other way.
Edit: some minor changes in code. I have missed few pointer marks in it.
Just to check we have our terminologies in synch - in my book, a factory class is a class instances of which can create instances of some other class or classes. The choice of which type of instance to create is based on the inputs the factory receives, or at least on something it can inspect. Heres's a very simple factory:
class A { ~virtual A() {} };
class B : public A {};
class C : public A {};
class AFactory {
public:
A * Make( char c ) {
if ( c == 'B' ) {
return new B;
}
else if ( c == 'C' ) {
return new C;
}
else {
throw "bad type";
}
}
};
If I were you I would start again, bearing this example and the following in mind:
factorioes do not have to be singletons
factories do not have to be static members
factories do not have to be members of the base class for the hierarchies they create
factory methods normally return a dynamically created object
factory methods normally return a pointer
factory methods need a way of deciding which class to create an instance of
I don't see why your factory needs reflection, which C++ does not in any case support in a meaningful way.
Basing this on the answer by #Shakedown, I'll make Base be templated on the actual type, using the CRTP:
template <class T>
class Base
{
public:
static std::auto_ptr<Base<T> > construct()
{
return new T();
}
};
class First : public Base<First>
{
};
class Second : public Base<Second>
{
};
This is nice because construct is now once again a static member. You would call it like:
std::auto_ptr<First> first(First::construct());
std::auto_ptr<Second> second(Second::construct());
// do something with first and second...
You can create a Singleton class and a NonSingleton class, and make all the descendants inherit one of them.
class Base {
public:
static Base *New() = 0;
}
class SingletonDescendant: public Base {
public:
*Base::New() {
if (Instance != NULL)
return Instance = new /* descendant constructor */;
else
return Instance;
}
private:
static Base *Instance;
}
SingletonDescendant::Instance = NULL;
class NonSingletonDescendant: public Base {
public:
*Base::New() {
return new;
}
}
class First : public SingletonDescendant{ // singleton descendant
}
class Second : public NonSingletonDescendant{ // normal descendant
}
It solves the issues that you raised:
How to declare static variable Instance, so it would be static in descendant classes: It exists only in the SingletonDescendant class.
How to call descendant constructors in base class: Using the New function
I have to write construct() method in every descendant; I consider it redundant, as it is obvious what it has to do: Now it is only in SingletonDescendant and NonSingletonDescendant.
How about something like this:
class Base
{
public:
virtual Base construct() = 0;
};
class First : public Base
{
public:
Base construct(){ return First(); // or whatever constructor }
};
class Second : public Base
{
public:
Base construct(){ return Second(...); // constructor }
};