I have this basic setup:
enum{
BASE,
PRIMITIVE,
...
};
class IUnknown{
public:
bool inline is(int type){return inv_type == type;}
private:
enum {inv_type = BASE};
};
class Primitive: public IUnkown{
private:
enum {inv_type = PRIMITIVE};
};
My problem is that I would want to be able to call is on a Primitive instance and have it return true when type is equal to the value in the enum I have declared in the Primitive class.
The only solution I have found is to declare the 'is' function as virtual and have a copy in every subclass, but I wondered if it would be possible to somehow redefine the enum and have the is function in IUnkown take the value from there
You could have your IUnknown class define a protected constructor (which would then have to be called from each derived class). It would take one of the enum values and store it. The stored value would then be compared against in the is() method.
If you don't like this, and prefer to add a virtual is() method to IUnknown, but don't want to have to define it in every derived class, you could do this:
template <int Tinv_type>
class IUnknownT : public IUnknown{
public:
virtual bool is(int type){return inv_type == type;}
protected:
enum {inv_type = Tinv_type};
};
class Primitive: public IUnknownT<PRIMITIVE>{
};
enums by themselves don't take up storage space because they're just lists of acceptable values for an enum variable. You have to have some runtime storage going on for a virtual function to actually work with the runtime type of the object. I would just use an int or something:
enum{
BASE,
PRIMITIVE,
...
};
class IUnknown{
public:
bool is(int type) const {return inv_type == type;}
protected:
IUnknown(int type) : inv_type(type) { }
private:
const int inv_type;
};
class Primitive: public IUnkown{
private:
Primitive() : IUnknown(PRIMITIVE) { }
};
Why not go all out and use strings instead of enums.
const char * baseStr = "base";
const char * derived1Str = "derived1";
const char * derived2Str = "derived2";
class base
{
public:
virtual bool is(const char * str)
{
return strcmp(baseStr, str) ? false : true;
}
};
class derived1 : public base
{
public:
bool is(const char * str)
{
if ( strcmp(derived1Str, str) )
return base::iA(str);
return true;
}
};
class derived2 : public derived1
{
public:
bool is(const char * str)
{
if ( strcmp(derived2Str, str) )
return derived1::is(str);
return true;
}
};
This has the benefit that this
base * b = new derived2();
bool is = b->isA(baseStr);
sets is to true.
Related
I'm trying to make an abstract class, and one of the methods that its children must override should return an instance of the child class.
class JsonSerializable {
public:
virtual <child_of_JsonSerializable> fromJson(string jsonStr) const = 0;
};
class ConcreteSerializable : public JsonSerializable {
public:
ConcreteSerializable fromJson(string jsonStr) const {
return ConcreteSerializable();
}
};
I tried using templates following this answer, but I get an error that templates may not be virtual.
Is there a way to do what I'm looking for without using raw pointers as the return type?
You cannot create an object of an abstract type. And because you cannot create such an object, you also cannot return it. This is the reason why all examples returning a base/derived object, always return a pointer or some reference to the base class
struct B {
virtual B *fromJson(const std::string &jsonStr) const = 0;
};
struct D : public B {
D(const std::string &jsonStr);
D *fromJson(const std::string &jsonStr) const;
};
D *D::fromJson(const std::string &jsonStr) const
{
return new D(jsonStr);
}
Are you trying to implement something that historically was done using CRTP?
struct Interface {
virtual Interface *inflate(std::string const &json) = 0;
virtual ~Interface() {}
};
template<typename Child> struct Base: public Interface {
Interface *inflate(std::string const &json) { return new Child(json); }
};
struct Child: public Base<Child> {
Child(std::string const &json);
};
I'm trying to make a tree structure to manage data whose structure can change depending on the type.
Here is what I did for the base object
//Type1.. are the types of the leaves having Base as common parent
enum class EnumBase{Type1,Type2,Type3};
class Base {
protected:
EnumBase const _type;
Base(EnumBase typ) : _type(typ){}
public:
virtual ~Base() = default;
Base() = delete;
EnumBase getType() const {return _type;}
};
while this is to create and get different derived
template<class Leaf>
class Controller {
private:
std::shared_ptr<Leaf> _pt;
public:
template<class Derived>
void create() {
_pt = std::make_shared<Derived>();
return;
}
template<class Derived>
Derived & get(){
auto pt = std::dynamic_pointer_cast<Derived>(_pt);
if(!pt){
throw; //bad cast
}
return *pt;
}
};
The second level of the tree goes like:
enum class Type1Types{T1,T2};
class Type1 : public Base {
protected:
Type1Types const _type;
Type1(Type1Types typ) : Base(EnumBase::Type1), _type(typ){}
public:
virtual ~Type1() = default;
Type1() = delete;
Type1Types getType() const {return _type;}
};
class Type2; //...the same with EnumBase::Type2 and Type2Types
class Type3; //...the same with EnumBase::Type3 and Type3Types
with final implementations which may possibly include Controller for another data type:
class T1 : public Type1 {
public:
T1() : Type1(Type1Types::T1) {}
//... data of T1
};
class T2 : public Type1 {
public:
Controller<Type2> objType2;
//... other data for T2
};
The idea behind all this is that I can write:
int main(){
Controller<Type1> obj;
obj.create<T2>();
obj.get<T2>().objType2.create<somethinginType2>();
//...
}
Probably such pattern is overcomplicated (any comment and suggestion is welcomed) but a pattern exists and I believe that it is possible with some template magic and some recursion to write a general templated version of a leaf (Type1, Type2,..) so that I don't have to copy/paste the code and only change the type of the enum for the children (Type1Types) and the type for itself (EnumBase::Type1).
I was thinking of some structure like
template<class Me, class... Parents>
struct MagicStructure{
//some typedef
//my type
}
Any idea?
This question already has answers here:
c++ Function to return an enum?
(4 answers)
Closed 7 years ago.
i am having trouble with the following:
i need to use enum to enumerate 4 inherited classes (at this point they have no difference between them other the the enum) and then return the type via a virtual function called "whoAmI", i don't understand the syntax as to how i would do the return part
the following is the relevant code;
in class.h
virtual void whoAmI();
enum gettype { easyTile, cropTile, waterTile, mediumTile};
in class.cpp
void tile::whoAmI()
{
}
You can change the return type of your function to the name of your enum, then use = 0 to declare the base class is pure virtual.
class ITile
{
public:
enum class EType { easy, crop, water, medium };
virtual EType whoAmI() const = 0;
};
Then the derived classes can override this method to return the correct enum type, for example
class EasyTile : public ITile
{
public:
EasyTile() = default;
EType whoAmI() const override { return EType::easy; }
};
class CropTile : public ITile
{
public:
CropTile() = default;
EType whoAmI() const override { return EType::crop; }
};
So as an example (live demo)
int main()
{
std::vector<std::unique_ptr<ITile>> tiles;
tiles.emplace_back(new EasyTile);
tiles.emplace_back(new CropTile);
for (auto const& tile : tiles)
{
std::cout << static_cast<int>(tile->whoAmI()) << std::endl;
}
}
Will output
0
1
You can easily do it like that:
class TileBase
{
public:
enum Type { easyTile, cropTile, waterTile, mediumTile };
virtual Type whoAmI() const = 0;
virtual ~TileBase() = default;
};
class EasyTile : public TileBase
{
Type whoAmI() const override { return easyTile; }
};
You see, you need to specify the enum Type as return type instead of void.
#include <iostream>
using namespace std;
class Tile{
public:
enum getType { easyTile, cropTile, waterTile, mediumTile};
virtual getType whoAmI(){}
};
class easyTile:public Tile{
public:
getType whoAmI(){return getType::easyTile;}
};
class cropTile: public Tile{
public:
virtual getType whoAmI(){return getType::cropTile;}
};
class waterTile: public Tile{
public:
virtual getType whoAmI(){return getType::waterTile;}
};
class mediumTile: public Tile{
public:
virtual getType whoAmI(){ return getType::mediumTile;}
};
int main() {
Tile *T = new cropTile;
cout << T->whoAmI() << endl;
delete T;
return 0;
}
Output : 1
I have got this problem and don't know how to solve it.
Suppose I have these base classes:
class ValueBase
{
private:
int base_value;
public:
int GetValue();
void SetValue(int val);
virtual ValueBase* Meet(ValueBase* const a, ValueBase* const b) = 0;
}
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val);
}
and derived class:
class Value : public ValueBase
{
public:
Value* Meet(ValueBase* a, ValueBase* b) override;
}
Is there a way to create instance of class Value in method AddValue in class NodeBase? I know that I should probably make AddValue pure virtual and implement it in derived class of NodeBase, but is there possibility to do it without this option? Can I use e.g. template method or maybe a callback to method in Value that would construct that object? Or is it just too evil to do it?
EDITED:
I don't have access to derived class Value in class NodeBase
Add a creation member function:
class ValueBase
{
public:
virtual ValueBase * create() = 0;
// ...
};
Then in NodeBase you can use base_nodeValue->create().
Derived classes implement it:
class Value : public ValueBase
{
Value * create() override { return new Value; }
};
The more common form of this pattern is a clone function, though, which does not produce a default-constructed object of the same type, but a copy:
Derived * clone() override { return new Derived(*this); }
I see no approach without changing class definitions. However, there are many approaches that involve changing class definitions, depending on what you are "allowed" to use.
A. Make AddValue() templated on the object type it should create:
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
template<class ValueType>
bool AddValue(int val) { base_nodeValue = new ValueType; }
}
...
// other code that has access to Value
node.AddValue<Value>(10);
B. Create function that creates Value (forwarding any arguments to constructor if needed) and pass it as an argument toAddValue`:
// might need to adapt syntax
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val, ValueBase* (*creator)()) { base_nodeValue = (*creator)(); }
}
...
// other code that has access to Value
ValueBase* valueCreator() { return new Value; }
...
node.AddValue(10, valueCreator);
(May use a functor or a lambda here as well)
C. You can create a function in ValueBase that returns Value*.
class ValueBase
{
public:
static ValueBase* createValue();
};
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val) { base_nodeValue = ValueBase::createValue(); }
};
// in a separate cpp
ValueBase* ValueBase::createValue() { return new Value; }
This is in fact similar to a factory approach: you can have createValue() accept a parameter and create different ValueBases depending on it. Having ValueBase store some pointer to creator function, you can have it not know about Value at all, just initialize that pointer at some other place, like you can register a subclass in a factory table in base class.
Is there anyway to have a sort of virtual static member in C++?
For example:
class BaseClass {
public:
BaseClass(const string& name) : _name(name) {}
string GetName() const { return _name; }
virtual void UseClass() = 0;
private:
const string _name;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass("DerivedClass") {}
virtual void UseClass() { /* do something */ }
};
I know this example is trivial, but if I have a vector of complex data that is going to be always the same for all derived class but is needed to be accessed from base class methods?
class BaseClass {
public:
BaseClass() {}
virtual string GetName() const = 0;
virtual void UseClass() = 0;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() {}
virtual string GetName() const { return _name; }
virtual void UseClass() { /* do something */ }
private:
static const string _name;
};
string DerivedClass::_name = "DerivedClass";
This solution does not satify me because I need reimplement the member _name and its accessor GetName() in every class. In my case I have several members that follows _name behavior and tenths of derived classes.
Any idea?
Here is one solution:
struct BaseData
{
const string my_word;
const int my_number;
};
class Base
{
public:
Base(const BaseData* apBaseData)
{
mpBaseData = apBaseData;
}
const string getMyWord()
{
return mpBaseData->my_word;
}
int getMyNumber()
{
return mpBaseData->my_number;
}
private:
const BaseData* mpBaseData;
};
class Derived : public Base
{
public:
Derived() : Base(&sBaseData)
{
}
private:
static BaseData sBaseData;
}
BaseData Derived::BaseData = { "Foo", 42 };
It seems like the answer is in the question - the method you suggested seems to be the right direction to go, except that if you have a big number of those shared members you might want to gather them into a struct or class and past that as the argument to the constructor of the base class.
If you insist on having the "shared" members implemented as static members of the derived class, you might be able to auto-generate the code of the derived classes. XSLT is a great tool for auto-generating simple classes.
In general, the example doesn't show a need for "virtual static" members, because for purposes like these you don't actually need inheritance - instead you should use the base class and have it accept the appropriate values in the constructor - maybe creating a single instance of the arguments for each "sub-type" and passing a pointer to it to avoid duplication of the shared data. Another similar approach is to use templates and pass as the template argument a class that provides all the relevant values (this is commonly referred to as the "Policy" pattern).
To conclude - for the purpose of the original example, there is no need for such "virtual static" members. If you still think they are needed for the code you are writing, please try to elaborate and add more context.
Example of what I described above:
class BaseClass {
public:
BaseClass(const Descriptor& desc) : _desc(desc) {}
string GetName() const { return _desc.name; }
int GetId() const { return _desc.Id; }
X GetX() connst { return _desc.X; }
virtual void UseClass() = 0;
private:
const Descriptor _desc;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(Descriptor("abc", 1,...)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass("Wowzer", 843,...) {}
virtual void UseClass() { /* do something */ }
};
I'd like to elaborate on this solution, and maybe give a solution to the de-initialization problem:
With a small change, you can implement the design described above without necessarily create a new instance of the "descriptor" for each instance of a derived class.
You can create a singleton object, DescriptorMap, that will hold the single instance of each descriptor, and use it when constructing the derived objects like so:
enum InstanceType {
Yellow,
Big,
BananaHammoc
}
class DescriptorsMap{
public:
static Descriptor* GetDescriptor(InstanceType type) {
if ( _instance.Get() == null) {
_instance.reset(new DescriptorsMap());
}
return _instance.Get()-> _descriptors[type];
}
private:
DescriptorsMap() {
descriptors[Yellow] = new Descriptor("Yellow", 42, ...);
descriptors[Big] = new Descriptor("InJapan", 17, ...)
...
}
~DescriptorsMap() {
/*Delete all the descriptors from the map*/
}
static autoptr<DescriptorsMap> _instance;
map<InstanceType, Descriptor*> _descriptors;
}
Now we can do this:
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.BananaHammoc)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.Yellow)) {}
virtual void UseClass() { /* do something */ }
};
At the end of execution, when the C runtime performs uninitializations, it also calls the destructor of static objects, including our autoptr, which in deletes our instance of the DescriptorsMap.
So now we have a single instance of each descriptor that is also being deleted at the end of execution.
Note that if the only purpose of the derived class is to supply the relevant "descriptor" data (i.e. as opposed to implementing virtual functions) then you should make do with making the base class non-abstract, and just creating an instance with the appropriate descriptor each time.
I agree with Hershi's suggestion to use a template as the "base class". From what you're describing, it sounds more like a use for templates rather then subclassing.
You could create a template as follows ( have not tried to compile this ):
template <typename T>
class Object
{
public:
Object( const T& newObject ) : yourObject(newObject) {} ;
T GetObject() const { return yourObject } ;
void SetObject( const T& newObject ) { yourObject = newObject } ;
protected:
const T yourObject ;
} ;
class SomeClassOne
{
public:
SomeClassOne( const std::vector& someData )
{
yourData.SetObject( someData ) ;
}
private:
Object<std::vector<int>> yourData ;
} ;
This will let you use the template class methods to modify the data as needed from within your custom classes that use the data and share the various aspects of the template class.
If you're intent on using inheritance, then you might have to resort to the "joys" of using a void* pointer in your BaseClass and dealing with casting, etc.
However, based on your explanation, it seems like you need templates and not inheritance.
#Hershi: the problem with that approach is that each instance of each derived class has a copy of the data, which may be expensive in some way.
Perhaps you could try something like this (I'm spit-balling without a compiling example, but the idea should be clear).
#include <iostream>
#include <string>
using namespace std;
struct DerivedData
{
DerivedData(const string & word, const int number) :
my_word(word), my_number(number) {}
const string my_word;
const int my_number;
};
class Base {
public:
Base() : m_data(0) {}
string getWord() const { return m_data->my_word; }
int getNumber() const { return m_data->my_number; }
protected:
DerivedData * m_data;
};
class Derived : public Base {
public:
Derived() : Base() {
if(Derived::s_data == 0) {
Derived::s_data = new DerivedData("abc", 1);
}
m_data = s_data;
}
private:
static DerivedData * s_data;
};
DerivedData * Derived::s_data = 0;
int main()
{
Base * p_b = new Derived();
cout getWord() << endl;
}
Regarding the follow-up question on deleting the static object: the only solution that comes to mind is to use a smart pointer, something like the Boost shared pointer.
It sounds as if you're trying to avoid having to duplicate the code at the leaf classes, so why not just derive an intermediate base class from the base class. this intermediate class can hold the static data, and have all your leaf classes derive from the intermediate base class. This presupposes that one static piece of data held over all the derived classes is desired, which seems so from your example.