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.
Related
How do I ensure my derived class implements at least one of two chosen methods in the base class?
class base {
public:
virtual int sample()=0;
virtual Eigen::VectorXf sample()=0;
};
class Derived : Base {
int sample() override {return 1;}
}
This code returns an error, as the sample method is not implemented with the VectorXf return type. However, my intention is that only one of these need to be implemented. The only reason they are seperate in the base class is that they have different return type. How can I do this in C++?
Overloading by return type is not possible. You may use std::variant instead:
#include <variant>
class Base {
public:
virtual std::variant<int, Eigen::VectorXf> sample()=0;
};
class Derived : public Base {
std::variant<int, Eigen::VectorXf> sample() override {return 1;}
};
If one is restricted to C++11, then there are many alternatives.
Implement and use something like variant: a class that has a enumerator selecting between two active types, and a union to contain these types.
Use Boost variant.
std::pair
Implement a hierarchy of classes (a simplification of std::any), and return on the right pointer to object:
class AbstractBase {
public:
virtual ~AbstractBase() = 0;
template <class T>
const T* get() const;
};
template <class T>
class ValueWrapper : public AbstractBase {
public:
ValueWrapper(const T& value) : m_value(value) {}
const T & getValue() const { return m_value; }
private:
T m_value;
};
template <class T>
inline const T * AbstractBase::get() const {
auto child = dynamic_cast<ValueWrapper<T> const*>(this);
return child ? &child->getValue() : nullptr;
}
class Base {
public:
virtual std::unique_ptr<AbstractBase> sample()=0;
};
The question is, why would you need this?
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 have a class template that derives from a parent class. I am storing the children in a vector as Parent*. I can later use typeid to determine if two objects are the same type. What I want to do is compare a property of two objects that are the same type. For simplicity, I have omitted storing the objects in a vector, but the concept is demonstrated below:
#include <iostream>
#include <typeinfo>
#include <vector>
class Parent{ public: virtual ~Parent(){}};
template<typename T>
class TypedChild : public Parent
{
public:
virtual ~TypedChild(){}
T getValue() {return mValue;}
private:
T mValue;
};
int main()
{
Parent* child1 = new TypedChild<int>();
Parent* child2 = new TypedChild<float>();
std::vector<Parent*> objects;
objects.push_back(child1);
objects.push_back(child2);
if(typeid(*(objects[0])) == typeid(*(objects[1])))
if(objects[0]->getValue() == objects[1]->getValue()) // compiler error: Parent has no member named getValue
std::cout << "Success";
return 0;
}
Of course in this example I could dynamic_cast to TypedChild<int> before calling getValue(), but in the real case where the objects are in a vector I don't know their types, I just know that they are the same type so their getValue() functions should return the same type and can hence be compared.
Is there any way to do this comparison?
With your use case, being able to avoid a dynamic_cast will be hard, if not impossible. If you want to get the value of just one object, you'll need to use dynamic_cast, such as:
Parent* child = ...;
auto typedChild = dynamic_cast<TypedChild*>(child):
if ( typedChild )
{
int val = typedChild->getValue();
}
If you want to compare two objects for equality, the best case scenario is to have a virtual operator==() function.
class Parent
{
public:
virtual ~Parent(){}
virtual bool operator==(Parent const& rhs) const = 0;
};
template<typename T>
class TypedChild : public Parent
{
public:
virtual ~TypedChild(){}
T getValue() {return mValue;}
virtual bool operator==(Parent const& rhs) const
{
auto derivedRHS = dynamic_cast<TypedChild<T> const*>(&rhs);
if ( !derivedRHS )
{
return false;
}
return (this->mValue == derivedRHS->mValue);
}
private:
T mValue;
};
I have a generic IDetachable interface, which provides one method:
template<class T>
class IDetachable {
public:
virtual T detached() const = 0;
};
I have these example classes:
class A: public IDetachable<A> {
virtual A detached() const override {
// some implementation which returns a detached A object
}
};
The problem occurs when inheriting B:
class B: public A, public IDetachable<B> {
virtual B detached() const override {
// some implementation which returns a detached B object
}
};
clang++ tells me:
error: virtual function 'detached' has a different return type ('B')
than the function it overrides (which has return type 'A')
To me it seems, that the compiler automatically chose the first parent for the override keyword. Is there any chance to tell the compiler which parent's method I intended to inherit with the override keyword?
The problem isn't about how to override one or the other its the fact that you can't have two functions with the same signature and different return types.
Consider:
template<class T, class U>
class IDetachable {
public:
virtual ~IDetachable() {}
virtual T detached() const = 0;
virtual U detached() const = 0; // whoopse problem
};
It doesn't matter how you end up with two same-signature functions returning different types its always illegal.
#AdrianMay provides a working answer. He changes the signatures of the functions.
You could pass a dummy T to detach:
template<class T>
class IDetachable {
public:
virtual T detached(T*dummy) const = 0;
};
You ignore that parameter but now you can specialise on it.
Do you just want return type covariance? It works only on pointers and references:
template<class T>
class IDetachable {
public:
virtual T* detached() const = 0;
};
class A: public IDetachable<A> {
virtual A* detached() const override {
// some implementation which returns a detached A object
}
};
class B: public A, public IDetachable<B> {
virtual B* detached() const override {
// some implementation which returns a detached B object
}
};
int main() {
IDetachable<A> *da = new A;
A *a = da->detached();
IDetachable<B> *db = new B;
B *b = db->detached();
}
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.