Inherit from a virtual class and specify it during construction - c++

I would like to have the class (for instance, ATLAS), that inherits from a virtual class (for instance, MAP) so, that one of the specializations of MAP can be specified in the constructor of ATLAS (for instance, physicalMap or politicalMap). I wonder if it would be possible with C++?
class map {...};
class physicalMap: public virtual map {...};
class politicalMap: public virtual map {...};
class atlas: public virtual map {
atlas(int i): physicalMap(){...}
atlas(inti, int j): politicalMap(){...}
...
};
How do I specify the specialization I want?

You can't delegate constructor to "sister" (class that inherit the same base class) class constructor.
However with templates you can inherit from the template parameter and do something like that:
class map {...};
class physicalMap: public virtual map {...};
class politicalMap: public virtual map {...};
template<typename Map>
class atlas: public virtual Map {
atlas(int i): Map(){...}
...
};
...
atlas<physicalMap> a;
...

You don't need virtual inheritance for this. You may consider using template meta programming, wherein you can pass the class type itself as the template type parameter.
Example:
template<typename TargetClass>
class Map
{
// Work with TargetClass
// This class and the "target" class would know each other well
// in terms of what methods/variables are there in target class.
};
class PhysicalMap : Map<PhysicalMap>
{};
class PoliticalMap : Map<PoliticalMap>
{};
I have skipped Atlas to keep things simple (and understandable). If you need Atlas, you may skip these 2 intermediate classes (as inherited from Map<>), and instantiate PhysicalMap and PoliticalMap this way.
class PoliticalMap; // non-templated
class PhysicalMap;
class Atlas
{
// Instantiate maps
Map<PoliticalMap> _politicalMap;
Map<PhysicalMap> _physicalMap;
};
Ideally, you need to reconsider your class design and ideology.

The natural design here seems to use a member that points to a map. For example using unique_ptr
struct map
{
virtual ~map(); // required for unique_ptr to work
...
};
class atlas
{
std::unique_ptr<map> _map;
public:
atlas(int i)
: _map(i==0? new physicalMap():
i==1? new politicalMap():nullptr)
{
if(!_map)
throw std::runtime_error("not map");
}
};
You may still inherit from map, then
class atlas : public map
{
public:
/* implement public interface of map using _map */
};
although this is a bit cumbersome.

Related

shared_ptr polymorphism on templated type

std::shared_ptr allows for polymorphism of the stored type, for instance:
class A {};
class B: public A {};
I can have std::vector<std::shared_ptr<A>> that holds B objects.
But what if I want to take this a step further and make A a template and store std::shared_ptrs of different specializations of A. For instance:
template<typename T> class A {};
class Strategy {};
class StrategyOne : public Strategy {};
class StrategyTwo : public Strategy {};
Is it possible to have a std::vector<std::shared_ptr<A<Strategy>>> that can store StrategyOne and StrategyTwo type objects at the same time?
Igor Tandetnik is exactly correct, an A<Strategy> has nothing in common with an A<StrategyOne>.
That said, in my case I realized that A is a trivial class, in my case a factory. That meant I could simply make Strategy inherit and specialize A to solve my problem. Simplified it becomes something like this:
template<typename T> class A {
public:
virtual T* get() = 0;
};
class Strategy : public A<Strategy> {
public:
virtual Strategy* get() { return new Strategy; }
};
class StrategyOne : public Strategy {
public:
virtual StrategyOne* get() { return new StrategyOne; }
};
Now Strategy and StrategyOne are both A<Strategy> types so I can store them in a shared_ptr<A<Strategy>. Due to polymorphic return types, StrategyOne's get() method can be called from A<Strategy> and usefully for me, I can still use StrategyOne to directly get a StrategyOne *.

C++ Storing child objects in a common container

I have a set of abstract parent classes in a namespace, similar to the following
namespace Core {
class Sparse;
class Dense;
}
I define those classes somewhere and after that I derive some child classes:
class SparseA: public Core::Sparse;
class SparseB: public Core::Sparse;
class DenseA: public Core::Dense;
Now I want to instantiate some objects of the child classes and store them in a common container that can be accessible from anywhere. How can I do this?
And another question: Should I include the child classes in the Core namespace aswell?
Thank you.
As long classes Sparse and Dense are unrelated, you can't store instances of derived classes in the same c++ standard container (unless you're going to use such fancy stuff as boost::variant or boost::any).
If you give them a common (abstract) base class you can use smart pointers ( e.g. std::unique_ptr<> or std::shared_ptr) to keep referencing them in a container (using the same pseudo syntax as in your sample)
namespace Core {
class CommonBase;
class Sparse : public CommonBase;
class Dense : public CommonBase;
}
typedef std::vector<std::unique_ptr<Core::CommonBase>> MyContainerType;
Another option might be a template wrapper class solution
namespace Core {
class WrapperBase {
public:
// Expose the common interface of Sparse and Dense as
// pure virtual functions
virtual void foo() = 0;
virtual ~WrapperBase() {}
};
template<class Impl>
class Wrapper : public WrapperBase {
private:
Impl& impl_;
public:
Wrapper(Impl& impl) : impl_(impl) {}
void foo() {
impl.foo(); // Delegate to the actual implementation
}
};
class Sparse;
class Dense;
}
typedef std::vector<std::unique_ptr<Core::WrapperBase>> MyContainerType;
MyContainerType container;
container.push_back(std::make_unique<Wrapper<SparseA>>());
container.push_back(std::make_unique<Wrapper<SparseB>>());
container.push_back(std::make_unique<Wrapper<DenseA>>());
The latter will allow to loosely couple classes like Sparse and Dense within a single container, but still at least requires some abstract interface, that could be be used behaviorally consistent for both classes, and classes derived from them.

OOP design - inheriting from container with generic type

I have two classes, say CollectionA and CollectionB, both inheriting from a Collection. Collection has an std::array<GenericType> attribute. I want to use CollectionA as a Collection whose inherited std::array contains elements of type ClassA (std::array<ClassA>) and CollectionB as containing an std::array<ClassB>. Is this possible, and if so how can I implement this design?
Note: I am not familiar with templates, if they are required for this problem.
EDIT: Collection is user-defined, so I'm not directly inheriting from std::array
A template would be the obvious solution, start with
template<typename Element>
class Collection
{
protected:
std::array<Element> arrr_;
};
class CollectionA : public Collection<ClassA>
{
};
class CollectionB : public Collection<ClassB>
{
};
Hope it helps...
Define them as so
class ContainerA : public Container<ClassA> {...};
class ContainerB : public Container<ClassB> {...};
template <class T>
class Collection {
protected:
std::array<T> data_;
};
class CollectionA : public Collection<A> {
/*
you can use data_ in this class.
data_ will be of type std::array<T>;
*/
};

Is there an interface mechanism for nested enum classes?

In C++, pure virtual functions provide the functionality of an interface. That is, any subclasses must implement all pure-virtual functions in the base class:
class myClass {
virtual bool implementme() = 0; // MUST be implemented
};
class mySubClass : public myClass {
bool implementme() {} // REQUIRED
};
Is there a similar mechanism for nested (enum) classes? That is, I'm looking for something like
class myClass {
virtual enum class myEnum = 0; // MUST be implemented
};
class mySubClass : public myClass {
enum class myEnum {}; // REQUIRED
};
Since you say that the implementer is not part of your code base (thus not producing a compile error), I must assume you are writing a library, and that the code which uses this enum is in the consumer of the library.
I would recommend that you use CRTP as follows:
class myClass {
};
template<typename T> class myClassImpl : public myClass {
static_assert(std::is_enum<typename T::myEnum>::value, "Subclasses of myClassImpl must provide the myEnum enum class");
};
class mySubClass : public myClassImpl<mySubClass> {
enum class myEnum {};
};
This wouldn't make a whole lot of sense. Someone could only have visibility to only the base class (not the derived class) and get back a myEnum from the return of some virtual function, where myEnum is an incomplete type. There is no mechanism for virtual types of any kind, including enums. Do you really want a virtual table looking up your type anyway?

c++ How do you call a templated base-class function from derived class instance

Found related questions but not the exact variant so I am posting a very simple question.
A derived class inherits from a templated base, and I want to call the base function, how to do it?
template <class A>
class testBase {
public:
void insert(const A& insertType) {
// whatever
}
};
class testDerived : testBase<double> {
// whatever
};
int main() {
testDerived B;
// Compiler doesn't recognize base class insert
// How do you do this?
B.insert(1.0);
}
Need public inheritance (default is private for class):
class testDerived : public testBase<double> {
A class has a default access level of 'private'. You basically inherited 'testBase' using private inheritance so that testBase's public interface is not part of testDerived's. Simple solution:
class testDerived: public testBase<double> {...};
I do wish C++ applied public inheritance by default though since that's generally a much more common case. Then again, we could just all use structs instead. :-D