Alternative to virtual static functions in c++? - c++

In the header file .hpp:
class Base{
public:
static /*Some Return Type*/ func(/*Some Datatype*/);
}
class Derived1 public Base{
public:
Derived1();
~Derived1();
}
class Derived1 public Base{
public:
Derived2();
~Derived2();
}
In the cpp file .cpp:
/*Some Return Type*/ Derived1::func(/*Some Datatype*/){
}
/*Some Return Type*/ Derived2::func(/*Some Datatype*/){
}
This obviously fails because there is no way to override a static method in a subclass. But how to obtain the above functionality?
It is mandatory for me to call something like this:
/*Some Return Type*/ result = Derived1::func(/*Some Datatype*/)
/*Some Return Type*/ result = Derived2::func(/*Some Datatype*/)
I know, that abstract method can be defined in the base class like below and then define them in Derived class:
In the header file .hpp:
class Base{
public:
virtual /*Some Return Type*/ func(/*Some Datatype*/) const = 0;
}
But the problem is that virtual methods require object instantiation, which is not I want. I want to call the method without creating an object. If virtual static methods were allowed, they would have served the purpose.
The only alternative that I can think of is to declare the function func() in all the Derived classes in the header file and remove it from the Base class. Is there any alternative method to do it? So that the declaration is only once in the Base class and all the Derived classes only have to define them, not redeclare?

Calling a virtual function without an object is a contrasense,
since the resolution depends on the type of the object.
are cases where you might need to call the same function
dependant on the type of an object, or specifying the class
explicitly, without an object. This is easily handled by using
two functions, one static, and one virtual. (Typically, the
virtual one will just forward to the static.)
EDIT:
A simple example (from actual code):
#define DECLARE_CLASS_NAME(className) \
static char className() { return STRINGIZE(className); } \
virtual char* getClassName() { return className(); }
class Base
{
public:
DECLARE_CLASS_NAME(Base);
// ...
};
class Derived : public Base
{
public:
DECLARE_CLASS_NAME(Derived);
// ...
};
and so on, in all of the derived classes. This was used to
obtain the type names for serialization, for example:
std::string typeName = pObj->getClassName();
and also as a primitive RTTI (this was about 20 years ago):
if ( pObj->getClassName() == Derived::className() ) ...
(We had established the rule that the only way you could obtain
the name of a class was by using one of these functions. That
effectively internalized the names of the classes, and allowed
simple pointer comparisons to work. On the systems we were
working on then, this was important.)

You can do that a bit hacky =)
//header file
template<class T>
struct base_t
{
static void do_smth();
};
struct derived1_t : base_t<derived1_t>
{
};
struct derived2_t : base_t<derived2_t>
{
};
//cpp file
void base_t<derived1_t>::do_smth() // `note base_t<derived1_t>::` instead of `derived1_t::`
{
std::cout << "aaa" << std::endl;
}
PS: very strange that you do not want to declare this function in derived classes, because when you use virtual functions you should declare them in derived class

One possibility is to only define them in the derived classes:
struct Base
{
// nothing
};
struct Derived1 : public Base
{
static void func() { /*...*/ }
};
struct Derived2 : public Base
{
static void func() { /*...*/ }
};
This allows you to call:
Derived1::foo();
Derived2::foo();
Calling it for the base type and expecting the compiler to figure out which subtype you mean cannot work:
// How will the compiler know to choose
// between Derived1:: func or Derived2:: func ?
Base::func();
You might want to look at CRTP or type-traits for alternative approaches.

Related

Is there a way to have a member parameter type be a pointer to a derived class

I'm writing a module system for my program, where individual modules are initialised and shutdown by a system.
how this works is I call an Init() function that will initialise a static pointer of the class.
this works and is fine, however: I would like to abstract this into a class so the api is easier to maintain, but I don't know how to change the pointer type of the derived class automatically
for example, if I have the base class IModule:
class IModule {
public:
protected:
result Init();
result Shutdown();
private:
static IModule* s_instance;
};
is there a way I can write this class so that the derived class can be written as
class Derived : public IModule {
protected:
result Init();
result Shutdown();
}
and have Derived::s_instance evaluate to a Derived*
No, you can't have a variable whose type depends on the type of this. However, you can have a variable whose type depends on a template parameter.
template <typename T>
class IModule {
private:
static T* s_instance;
};
class Derived : public IModule<Derived> {
// The s_instance in this class is of type Derived*.
}
This is called the curiously recurring template pattern and it's used to do all sorts of tricks in C++. It may not work for your use case (for instance, you can no longer have a list of IModule which all have different derived types), but depending on what exactly you're doing this may be the way to go.
You can do this as long as the return types are covariant, i.e., Derived::Init() returns something derived from Derived::IModule()'s return type. Which is I think the case here. A simplified version:
#include <iostream>
struct IModule {
virtual IModule* Init() = 0;
private:
static IModule* s_instance;
};
class Derived : public IModule {
Derived* Init() override { std::cout << "1" << std::endl; return this; }
};
int main() {
IModule* ptr = new Derived();
ptr->Init(); // compile-time type: IModule, runtime: Derived
}

Access derived class's method covariant return, with derived constructed from factory with unique_ptr<AbstractBase>

Edit: My question might just be asking how to downcast a unique_ptr<base> to unique_ptr<derived> (which is already answered), but I am not 100% sure what I am asking
I have an Abstract Base Class Base
class Base{
public:
Base();
struct pStruct{};
virtual pStruct pFunc(std::vector<double> data) = 0;
protected:
CustomType dataValue;
};
and two derived classes Derived1 and Derived2 that implement Base
class Derived1 : public Base {
public:
struct pStructD1 : Base::pStruct {
CustomType data1;
std::vector<double> data2;
};
Derived1(uint32_t foo1, std::vector<double> foo2, ...);
virtual pStruct pFunc(std::vector<double> data) override;
private:
uint32_t bar1{0};
};
class Derived2 : public Base {
public:
struct pStructD2 : Base::pStruct {
int32_t data3;
std::vector<double> data4;
double data5
};
Derived2(std::vector<double> foo1, std::vector<double> foo2, ...);
virtual pStruct pFunc(std::vector<double> data) override;
private:
std::vector<double> bar2;
};
When calling class method pFunc(std::vector<double> data), each derived class will return different types, and amounts of values. I tried making this work with a covariant return type, so Derived1::predict(data).key1 might be a matrix, and .key2 might be something else, and so on. Derived2::predict(data).key1 might be the only key, and it could be a boolean. Each derived class defines their own ::predict() return fields, because they vary significantly.
The issue is, I construct these derived classes with a factory, that reads some of the input (construction is via ifstream), and figures out what derived class it should be, and then calls the corresponding factory.
class BaseFactory {
public:
static std::unique_ptr<Base> createObj(std::ifstream & file){
file.read((char *) specificTypeString, 2);//This isn't actually the code, just assume this part works
if(specificTypeString == "D2"){
return D2BaseFactory::createObj(file);
}
else if(specificTypeString == "D1"){
return D1BaseFactory::createObj(file);
}
else{
throw std::runtime_error("error");
}
}
};
With std::unique_ptr<Base> D1BaseFactory::createObj(std::ifstream & file); returning std::unique_ptr<Derived1>(new Derived1(param1, param2, ...)); and the same thing for `D2BaseFactory'.
Problem is, if I construct a Derived class with the common BaseFactory, and call pFunc() on the returned unique_ptr, it always will be the empty Base::pStruct == {} and thus trying to access members of the covariant pStructs isn't possible. I know this is because the factory createObj returns the base type, but is there any way to dynamically return the type I want so I can access the necessary fields in the derived pStructs? I think using raw pointers might work, but if possible i'd like to keep them as unique pointers.
You can do something similar to this:
class Base
{
public:
...
std::unique<pStruct> pFunc(...) { return DopFunc(); }
protected:
virtual std::unique<pStruct> DopFunc() = 0;
};
class Derived1 : public Base
{
public:
struct pStructD1 : Base::pStruct { ... };
// Used when calling the child factory directly...
std::unique_ptr<pStructD1> pFunc(...)
{
return std::make_unique<pStructD1>(...);
}
protected:
// Used when called through the Base factory...
std::unique<pStruct> DopFunc(...) override
{
// Call the other function for code sharing... (DRY)
return pFunc(...);
}
....
};
This could make sense if you used the derived class when you need the derived objects.
The real question is why you need to used the derived types... If it is for initialisation purpose, then maybe the factory should do it before returning the value.
If it is for some processing, then maybe you should have some virtual functions in pStruct. That way, you never need to know the derived type returned by the factory.
In some case, the visitor pattern might also be a solution.
If you need to always use the specific struct, then why not always use the specific factory too?
You can also cast the result but if you need to do it every time you create an object, it might make the code more complex that it need to be.
Alternatively, you could also have a template member function let say template <class T> std::unique_ptr<T> pFuncT(...) { ... }. That way, the client code can specified the desired type directly at construction. An empty object or an exception could be throw if the type is incorrect.

Can I use CRTP with multiple derived classes, and use them polymorphically?

I have such hierarchy of classes:
template <class Type>
class CrtpBase
{
protected:
Type& real_this()
{
return static_cast<Type&>(*this);
}
};
template <class ChildType>
class Base : CrtpBase<ChildType>
{
public:
void foo()
{
this->real_this().boo();
}
};
class Derived1 : public Base<Derived1>
{
public:
void boo { ... }
};
class Derived2 : public Base<Derived2>
{
public:
void boo { ... }
};
The thing is, I want to use my classes in this way:
std::vector<Base*> base_vec;
base_vec.push_bach(new Derived1());
base_vec.push_bach(new Derived2());
.........
base_vec[0]->foo();
But this isn't possible, because base class for all derived classes is different (actually Base isn't a type at all, it's template). So, is there a way to use crtp with multiple derived classes, alongside with polymorphism?
Indeed there is, you need to add the appropriate non-template base class too:
class AbstractBase
{
public:
virtual ~AbstractBase() {}
virtual void foo() = 0;
};
template <class ChildType>
class Base : CrtpBase<ChildType>, public AbstactBase
{
void foo() override { this->real_this().boo(); }
};
Then, declare your vector as std::vector<AbstractBase*>.
This does indeed introduce the overhead of dynamic dispatch (which you were probably trying to avoid by using CRTP), but dynamic dispatch is the only way to get runtime polymorphism in C++.
It can still be beneficial, though. For example, if the implementation of foo is shared by all the derived classes, but calls into many different boo-style functions (with each derived class having a different implementation of those), you will only pay the dynamic dispatch cost once when invoking foo, and then all the calls made within foo are dispatched statically, CRTP-style.
On the other hand, if it's just one call to a boo-like function within foo, you may as well make boo virtual, put non-virtual foo into the base, thus getting rid of CRTP. The cost will be the same then: a non-virtual dispatch (foo) and a virtual one (boo).
Side note, you should strongly consider storing smart pointers in the std::vector; owning raw pointers are bad practice.

Override a data member in a C++ derived class

I have an doubt, with C++ redefinition. I assign memory in Derived class, so I need that this memory is reserved in Base class. So, I need considered that the attibute in the Base class is the same that the attribute in the Derived class, and I don't know is that is possible in C++.
class Base {
protected:
float * a;
Base() {}
public:
virtual void reset() {
a = 0;
}
virtual void exec() {
printf("Memory a: %x\n",a);
}
};
class Derivada: virtual public Base {
protected:
float * a;
Derivada() {}
virtual void reset() {
a = new float[256];
}
};
int main() {
Derivada *hija= new Derivada();
hija->reset();
hija->exec();
delete hija;
}
I really need do overloading, because it is an example of my real problem. I have the same test (Derived an main, code), for two different class Base, one in each branch, of my two branchs, of CVS.
In one of this class Base, I have this attributes, an in the other class Base, I don't have this attributes, so I have to put it, in Derived class, for compiling.
I wouldn't like to have to make two different test codes, so I need override the attribute
You could do something like this (but requires C++11):
#include <type_traits>
// A way to check for 'attr' data member presence/absence using SFINAE
template<class T> constexpr auto missing_attr(T) -> decltype(T::attr, bool())
{
return false;
}
constexpr bool missing_attr(...) { return true; }
struct Base { /* There might be (or not) a float data member 'attr' */ };
template<bool> struct Inject;
template<> struct Inject<true> { float attr = 0.0; };
template<> struct Inject<false> {};
struct Derived : public Base, protected Inject<missing_attr(Base())>
{
void do_something_with_attr()
{
// Derived has only one 'float attr' (it can be from Base or from Inject).
a *= a;
}
};
There are other ways to detect if a data member exists, e.g. the member detector idiom (C++03 compatible).
Do not redeclare the member the the derived class. The word "protected" ensures visibility.
If you redeclare the member, you will have a new member. This is called shadowing. See, e.g.
http://www-personal.umich.edu/~saarela/programming/2009/07/c-variable-shadowing.html
http://en.wikipedia.org/wiki/Variable_shadowing

Testing for Type Equality without RTTI

Say B and C are derived from A. I want to be able to test whether any two instances of classes derived from A are instances of the same class, that is, whether A* foo and A* bar both point to B instances, without using RTTI. My current solution is something like this:
class A {
protected:
typedef uintptr_t Code;
virtual Code code() const = 0;
}; // class A
class B : public A {
protected:
virtual Code code() const { return Code(&identity); }
private:
static int identity;
}; // class B
class C : public A {
protected:
virtual Code code() const { return Code(&identity); }
private:
static int identity;
}; // class C
Using this method, operator== can simply test first.code() == second.code(). I'd like to remove the literal identity from the derived classes and have the code found automatically by A, so that not all of the derived classes have to repeat this idiom. Again, I would strongly prefer not to use RTTI. Is there any way to do this?
Note: I have seen recent questions [1] and [2], and this is not a duplicate. Those posters want to test the contents of their derived classes; I merely want to test the identities.
You should just use RTTI instead of reinventing the wheel.
If you insist on not using RTTI, you could use CRTP and a function-local static variable to avoid having to write the function to every derived class. Adapt from this example code I wrote for Wikipedia: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Polymorphic_copy_construction
Another alternative is reading the vtable pointer (via this and pointer arithmetics), but that would depend on both the compiler and the platform, so it is not portable.
Your idea is on the right track; maybe you can eliminate some boilerplate with a template:
class TypeTagged {
public:
virtual Code code() const = 0;
}
template <class T>
class TypeTaggedImpl: public virtual TypeTagged {
public:
virtual Code code() const { return Code(&id); }
private:
static int id;
}
Then your client classes just need to be declared like this:
class A: public TypeTaggedImpl<A> { ... }
class B: public A, public TypeTaggedImpl<B> { ... }
The different instantiations of TypeTagged mean that the types have different id fields and hence different IDs; the virtual base type means that the code for the most derived type gets returned.
You can have the Base class to take id as a constructor parameter and implement the identity() function in base class itself. Then there is no need to repeat the code in derived classes. In the derived class constructor, you can do something like derived::derived(): base(0) Sample Code:
class A
{
public:
A(int n) : m_id(n)
{
}
virtual ~A(){}
virtual int id() const
{
return m_id;
}
private:
int m_id;
};
class B : public A
{
public:
B() : A(0)
{
}
};
you can use the both macro __FILE__ __LINE__ as your code
this will avoid the collision problem
you can map this values to an int