Consider the following code:
#include <stdio.h>
#include <iostream>
/// Header-file
class Base {
public:
virtual void do_something() const =0;
int GetAttrib () const {return constattribute_;};
static const int constattribute_;
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
};
class DerivedB : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
};
/// CC-file
using namespace std;
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
The intend being that i have some abstract interface (Base) which defines also a variable, which should be present for all derived classes, and is retrievable. All flavours of subclasses should be forced to/able to redefine their specific value for this variable, at best during class declaration (the values are known at the time the class is declared after all).
I want to achieve code, not altering the main()-program so that the output is '12' and not as of now (uncommenting current lines in the code) '00' (Doing so shadows the fields from base class).
I tried to look into the matter, and there are different paths for solutions, many of which however go contrary to my intuition:
1. Some follow the CRTP pattern, which is however impossible if I want to address my subclasses by their base-ptr in main.
2. Other solutions require to virtualize the 'GetAttrib()' function for every derived instance., which is cumbersome, and action of modifying the attribute is masked within a function definition.
3. A third possibility is to remove the static pattern and have the 'constattribute_' field as a regular member, which however forces me to drag it through all constructors as a parameter.
I am quite sure that there must be some smarter way to do this. Any hints are appreciated.
Using CRTP may get you what you want, assuming you don't have to access GetAttr() through Base* and can leave without constattribute_ in Base itself. Just follow the rule that every programming problem can be solved by entering another level of indirection, which I did below:
class Base {
public:
virtual void do_something() const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
If you need GettAttr from top to bottom of the inheritance tree you can modify the above code a bit, but this will cost you making GetAttr virtual (but still one implementation only):
class Base {
public:
virtual void do_something() const = 0;
virtual int GetAttrib () const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
Please note that I don't know how well (or bad) it will behave with deep inheritance tree (ie. when inheriting from DerivedA and/or DerivedB). In this case I would probably remove BaseConstAttr from inheritance tree right below Base and would try to inject it between most derived class and its predecessor or use multiple inheritance.
What you are requesting requires virtual dispatch somewhere, because you don't know the type of the object you are dealing with until runtime. The purpose of virtual dispatch is to solve exactly the problem you are facing.
The simplest solution is what you have given as number 2: make GetAttrib() virtual, and implement it on each derived class where you introduce a shadowing constattribute_.
static variable in base class is single instance hence it will be reflected same in derived class.
You can make same static member variable in derived class with specific different value you want. Now make getter member function of static variable in Base class as virtual and overload it in derived class which returns is static instance value.
I have update your code to work it, please check ..
#include <iostream>
using namespace std;
class Base {
public:
static const int constattribute_;
virtual void do_something() const =0;
virtual int GetAttrib () const {return constattribute_;};
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
class DerivedB : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
You should get desired output.
Note : Remember all member variables and func in derived class are private.
Related
If I have something like
class Base {
static int staticVar;
}
class DerivedA : public Base {}
class DerivedB : public Base {}
Will both DerivedA and DerivedB share the same staticVar or will they each get their own?
If I wanted them to each have their own, what would you recommend I do?
They will each share the same instance of staticVar.
In order for each derived class to get their own static variable, you'll need to declare another static variable with a different name.
You could then use a virtual pair of functions in your base class to get and set the value of the variable, and override that pair in each of your derived classes to get and set the "local" static variable for that class. Alternatively you could use a single function that returns a reference:
class Base {
static int staticVarInst;
public:
virtual int &staticVar() { return staticVarInst; }
}
class Derived: public Base {
static int derivedStaticVarInst;
public:
virtual int &staticVar() { return derivedStaticVarInst; }
}
You would then use this as:
staticVar() = 5;
cout << staticVar();
To ensure that each class has its own static variable, you should use the "Curiously recurring template pattern" (CRTP).
template <typename T>
class Base
{
static int staticVar;
};
template <typename T> int Base<T>::staticVar(0);
class DerivedA : public Base<DerivedA> {};
class DerivedB : public Base<DerivedB> {};
They will share the same instance.
You'll need to declare separate static variables for each subclass, or you could consider a simple static map in which you could store variables that are referenced by derived classes.
Edit: A possible solution to this would be to define your base class as a template. Having a static variable defined in this template would mean that each derived class will have it's own instance of the static.
There is only one staticVar in your case: Base::staticVar
When you declare a static variable in a class, the variable is declared for that class alone. In your case, DerivedA can't even see staticVar (since it's private, not protected or public), so it doesn't even know there is a staticVar variable in existence.
The sample code given by #einpoklum is not working as it is because of the missing initialization of the static member foo_, missing inheritance in FooHolder declaration, and missing public keywords since we are dealing with classes. Here is the fixed version of it.
#include <iostream>
#include <string>
class A {
public:
virtual const int& Foo() const = 0;
};
template <typename T>
class FooHolder : public virtual A {
public:
const int& Foo() const override { return foo_; }
static int foo_;
};
class B : public virtual A, public FooHolder<B> { };
class C : public virtual A, public FooHolder<C> { };
template<>
int FooHolder<B>::foo_(0);
template<>
int FooHolder<C>::foo_(0);
int main()
{
B b;
C c;
std::cout << b.Foo() << std::endl;
std::cout << c.Foo() << std::endl;
}
I know that this question has already been answered but I would like to provide a small example of inheritance with static members. This is a very nice way to demonstrate the usefulness as well as what is happening with the static variables and the respective constructors.
FooBase.h
#ifndef FOO_BASE_H
#define FOO_BASE_H
#include <string>
class FooBase {
protected:
std::string _nameAndId;
private:
std::string _id;
static int _baseCounter;
public:
std::string idOfBase();
virtual std::string idOf() const = 0;
protected:
FooBase();
};
#endif // !FOO_BASE_H
FooBase.cpp
#include "FooBase.h"
#include <iostream>
int FooBase::_baseCounter = 0;
FooBase::FooBase() {
_id = std::string( __FUNCTION__ ) + std::to_string( ++_baseCounter );
std::cout << _id << std::endl;
}
std::string FooBase::idOfBase() {
return _id;
}
std::string FooBase::idOf() const {
return "";
} // empty
DerivedFoos.h
#ifndef DERIVED_FOOS_H
#define DERIVED_FOOS_H
#include "FooBase.h"
class DerivedA : public FooBase {
private:
static int _derivedCounter;
public:
DerivedA();
std::string idOf() const override;
};
class DerivedB : public FooBase {
private:
static int _derivedCounter;
public:
DerivedB();
std::string idOf() const override;
};
#endif // !DERIVED_FOOS_H
DerivedFoos.cpp
#include "DerivedFoos.h"
#include <iostream>
int DerivedA::_derivedCounter = 0;
int DerivedB::_derivedCounter = 0;
DerivedA::DerivedA() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedA::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedA::idOf() const {
return _nameAndId;
}
DerivedB::DerivedB() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedB::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedB::idOf() const {
return _nameAndId;
}
main.cpp
#include "DerivedFoos.h"
int main() {
DerivedA a1;
DerivedA a2;
DerivedB b1;
DerivedB b2;
system( "PAUSE" );
return 0;
}
If __FUNCTION__ is not working for you in your constructors then you can use something similar that can replace it such as __PRETTY_FUNCTION__ or __func__, or manually type out each class's name :(.
Alas, C++ has no virtual static data members. There are several ways to simulate this, more or less:
#GregHewgill's solution has you replicate the static variable in each derived class; this solution is simple, straightforward and doesn't introduce additional classes, but I don't like this one since it's verbose, and you have to be rather disciplined with it.
#MarkIngram suggested a CRTP-based solution, which saves you most of the typing; however, it messes up the inheritance structure, because what were previously subclasses of A are no longer really related as classes. After all, two templated types with the same name but different template arguments could be just any two types.
I suggest a different CRTP-based solution, using a mix-in class:
class A {
virtual const int& Foo() const = 0;
}
template <typename T>
class FooHolder {
static int foo_;
const int& Foo() const override { return foo_; }
}
class B : A, virtual FooHolder<B> { }
class C : B, virtual FooHolder<B> { }
The only thing you need to do in a subclass is also indicate the mix-in inheritance. There might be some virtual inheritance caveats I'm missing here (as I rarely use it).
Note that you either have to instantiate and initialize each subclass' static variable somewhere, or you can make it an inline variable (C++17) and initialize it within the template.
This answer was adapted from my answer to a dupe question.
Let a class hierarchy :
class Base { virtual ~Base() throw(); };
class DerivedA : public Base { };
class DerivedB : public Base { };
I would like to have some code specific to each of these derived classes. However that code also being specific to the application that makes use of this class hierarchy, I do not want to embbed this derived-class-specific code into these derived classes. To avoid doing so, I thought about writing free functions :
void DerivedASpecificWork( DerivedA da );
void DerivedBSpecificWork( DerivedB db );
However, when given an instance of a derived class through a reference/pointer to a Base, I do not have access to the actual type of the instance, and thus cannot call the proper Derived*SpecificWork() function.
I would like to know if there is nome kind of design pattern that would allow me to call a derived-class-specific function without knowing the actual type of the instance, i.e having the same mechanism as virtual functions provide, but without having these virtual functions that would require me to embbed application-specific code into that class hierarchy.
Actually, why I want to do that is to provide informations about an exception that occured within a natively implemented function called by a Lua script. Each exception carrying its own set of information, the way I want to represent the error within the script depends on the type of the exception. I could create a pure virtual method in the base class that would be implemented by derived classes, but this would require me to embbed Lua-related code into my exception hierarchy, which I do not want to do since the Lua is specific to one of the application using that exception hierarchy.
Also I cannot use C++11.
Thank you.
May be Brigde pattern can help you.
This pattern can be used when you want to avoid a permanent binding between an abstraction and it's implementation.
(I don't see your comment about your restriction in using c++11, but you can remove std::unique_ptr, std::move and override keyword)
class AppSpecificImp
{
public:
virtual void DoWork() = 0;
};
class Base
{
public:
virtual ~Base() throw();
virtual DoWork() = 0;
};
class DerivedA : public Base
{
public:
DerivedA(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedA specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
class DerivedB : public Base
{
public:
DerivedB(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedB specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
Edit to show Visitor pattern usage:
With visitor pattern you can do what you want but with more Effort.
class Visitor
{
public:
virtual void VisitDerivedA(DerivedA* object) = 0;
virtual void VisitDerivedB(DerivedB* object) = 0;
};
class Base
{
public:
virtual void Visit(Visitor* visitor) = 0;
};
class DerivedA : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedA(this);
}
};
class DerivedB : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedB(this);
}
};
class AppSpecificVisitor : public Visitor
{
public:
void VisitDerivedA(DerivedA* object)
{
// Do any work related to DerivedA class
}
void VisitDerivedB(DerivedB* object)
{
// Do any work related to DerivedB class
}
}
int main()
{
AppSpecificVisitor myVisitor;
Base* myBase = // any class in your hierarchy
myBase->Visit(&myVisitor);
}
As I said in comments with Visitor pattern you can add new functionally without changing the main hierarchy(Base->Derived types). You just define a new visitor implementation and write your logic for every class in main hierarchy. In your example you can pack app specific logic in an object and reference that in your derived objects that is an easier approach.
Why not using a new set of hierarchy for application specific implementation ?
class AppBase
{
public:
virtual ~AppBase() throw();
virtual void work_with_app() = 0;
};
class Base
{
public:
Base(AppBase& app) : m_app(app) {}
virtual ~Base() throw();
protected:
AppBase& m_app;
};
class DerivedA : public Base { DerivedA(AppBase& app) : Base(app) {} };
class DerivedB : public Base { DerivedA(AppBase& app) : Base(app) {} };
// Application specific implementation :
class AppLuaSpecific : public AppBase
{
public:
void work_with_app() { /* Lua app specific */ }
};
This way, your 1st hierarchy : Base, DerivedA, DerivedB can live without knowing anything about the app specific code implemented in AppLuaSpecific.
You can implement your own app-specific dispatch as follows (check it live on Coliru):
#include <iostream>
#include <typeinfo>
struct Base { virtual ~Base() {} };
struct DerivedA : public Base { };
struct DerivedB : public Base { };
namespace AppSpecific
{
template<class F>
void dispatch(const Base& b)
{
const std::type_info& t = typeid(b);
if ( t == typeid(DerivedA) )
F::doit(static_cast<const DerivedA&>(b));
else if ( t == typeid(DerivedB) )
F::doit(static_cast<const DerivedB&>(b));
}
struct Foo
{
static void doit(const DerivedA& da) { std::cout << "Foo(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Foo(DerivedB)\n"; }
};
struct Bar
{
static void doit(const DerivedA& da) { std::cout << "Bar(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Bar(DerivedB)\n"; }
};
} // namespace AppSpecific
int main()
{
DerivedA da;
DerivedB db;
Base& b1 = da;
Base& b2 = db;
AppSpecific::dispatch<AppSpecific::Foo>(b1);
AppSpecific::dispatch<AppSpecific::Foo>(b2);
AppSpecific::dispatch<AppSpecific::Bar>(b1);
AppSpecific::dispatch<AppSpecific::Bar>(b2);
}
Here is what I am trying to achieve:
I have a list of Classes (Class1 to Classn) which inherit from a main Class
I would like to be able to instanciate an object of any of the n classes without having to do a large switch case (or equivalent). something along the lines of:
static ClassPointerType const * const ArrayOfClassTypes[]={ Class1, Class2, .. Classn };
static Class *GetObjectOfClass(int i)
{
return new ArrayOfClassTypes[i](some parameters for the constructor);
}
You can do that in other OO langues like Delphi where you have a TClass type and can get the class of an object... but I was not able to locate the equivalent functionality in C++.
Are you looking for something like this?
template<typename T>
std::unique_ptr<base> make()
{
return std::unique_ptr<base>(new T);
}
class factory
{
static constexpr std::unique_ptr<Base> (*fns[])(){make<derived_a>, make<derived_b>};
std::unique_ptr<base> get_object_of_class(int const i)
{
if (i < 0 || sizeof fns / sizeof *fns <= i) {
return nullptr;
}
return fns[i]();
}
};
You can add virtual method Clone to your base class and have it pure virtual (= NULL). Have there all required parameters.
Then you can override it in every subclass and create concrete classes there.
And in your factory do:
static ClassPointerType *GetObjectOfClass(int i)
{
return new ArrayOfClassTypes[i]->Clone(some params for the constructor);
}
And your array should contain concrete classes which you will clone:
static ClassPointerType* const ArrayOfClassTypes[]={ new ClassPointerType1(),new ClassPointerType2(), .. new ClassPointerTypeN() };
Complete example as requested:
// base class
class ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) = NULL;
};
// concrete classes
class ClassPointerType1 : public ClassPointerType
{
…
public:
// note: it clones own concrete instance
virtual ClassPointerType* Clone(your params) {return new ClassPointerType1(your params)};
}
class ClassPointerType2 : public ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) {return new ClassPointerType2(your params)};
}
…
class ClassPointerTypeN : public ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) {return new ClassPointerTypeN(your params)};
}
I implemented something alike recently. In my approach I stored a list of static create-functions instead and feeded a factory class with that
I implemented a templated base class wich
a) is able to register the derived into a factory class
b) implicitly forces the derived class to provide static functions.
However, you have to announce each derived class once. You can use it like this:
int main(int argc, char* argv[])
{
DerivedA::announce();
//and later
IInterface * prt = SingeltonFactory::create(DerivedA::_type);
delete prt;
return 0;
}
The Derived class DerivedA is defined as:
class DerivedA :
public IInterface,
public StaticBase<DerivedA>
{
public:
using StaticBase::announce;
static IInterface * create(){ return new DerivedA; }
static const std::string _type;
};
const std::string DerivedA::_type=std::string("DerivedA");
And the static Base class forcing the _type attribute and the create function to exist are defined as follows:
template<class TDerived>
class StaticBase
{
protected:
static void announce()
{
// register into factory:
SingeltonFactory::registerFun(TDerived::_type,TDerived::_create());
// The call of _type and _create implicitly forces the derived class to implement these, if it is deriving from this Base class
}
};
The factory class does contain a map of
std::map<std::string,tFunPtr>
where typedef tFunPtr is:
typedef IInterface * (*tFunPtr)(void);
This map you can use as an "array of classes" in order to handle it like an object. Thus, you represent the classes by a function pointer of the static create function
Does this answer your requirements? Shall I provide the factory class?
Assuming you are using a C++11 compiler here is a solution equivalent to the one provided earlier but less tricky and clever:
#include <iostream>
#include <memory>
#include <array>
class Base {
public:
virtual void doSomething() = 0;
};
class Der1: public Base {
private:
void doSomething() override {
std::cout << "Der1 did something" << std::endl;
}
};
class Der2: public Base {
private:
void doSomething() override {
std::cout << "Der2 did something" << std::endl;
}
};
template <typename T>
std::unique_ptr<Base> make() {
return std::unique_ptr<T>(new T);
}
int main() {
std::array<std::function<std::unique_ptr<Base>(void)>, 2> arr{make<Der1>,
make<Der2>};
auto obj = arr[0]();
obj->doSomething();
obj = arr[1]();
obj->doSomething();
}
You can use std::bind too to pass arguments to make if you have to use a non-default contructor
Hope that helps
No, in C++ classes are not first-order entities.
(I just noticed everybody is providing a solution to your problem but not precisely answering your question.)
I want to make a class with a member function that takes a reference to another class, where both classes are derived from abstract classes. I get a compiler error that the class Container is abstract because it doesn't implement addElem().
class Ielem
{
public:
virtual void action() = 0;
};
class Elem: public Ielem
{
public:
void action() {};
void extra() {};
};
class Icontainer
{
public:
virtual void addElem(Ielem &elem) = 0;
};
class Container: public Icontainer
{
public:
void addElem(Elem &elem) { elem.extra(); };
};
int main(int argc, char* argv[])
{
Elem e;
Container c;
c.addElem(e);
return 0;
}
It seems like this ought to work, because any reference to an Elem is also a reference to an Ielem. It compiles if I make Container::addElem take a reference to an Ielem. But then Container::addElem() can't call Elem::extra() unless I use dynamic_cast, which isn't available on the embedded compiler I'm using, or a regular cast, which isn't type safe.
Suggestions?
It's the wrong way round: the base class Icontainer specifies that addElem can take any Ielem object as an argument, but in your derived class you accept only Elem. This is a "narrower" type, so the contract "I'll accept any Ielem you throw at me" specified in the base class is violated.
I think templates would be the solution here. You don't even need the base classes anymore. Something like this:
class Elem
{
public:
void action() {};
void extra() {};
};
template<typename ElemType>
class Container
{
public:
void addElem(ElemType &elem) { elem.extra(); };
};
int main(int argc, char* argv[])
{
Elem e;
Container<Elem> c;
c.addElem(e);
return 0;
}
As a bonus, you can now use Container with any type that has an extra() function, and it will just work.
The problem is simply that your virtual method doesn't have the same signature as the concrete method which is intended to overload it; so the compiler sees it as a different function entirely and complains because you haven't implemented void addElem(Ielem &elem). This is one solution, which you probably don't want--
class Icontainer
{
public:
virtual void addElem(Elem &elem) = 0; //Ielem -> Elem
};
It depends on all your other constraints but I think what I would do--and what seems to conform to general design guidelines, e.g. Sutter & Alexandreascu, would be to create an intermediate abstract class with the full interface--
class Melem: public Ielem
{
public:
// void action() {}; //Already have this form Ielem
void extra() = 0;
};
and then
class Icontainer
{
public:
virtual void addElem(Melem &elem) = 0;
};
class Container: public Icontainer
{
public:
void addElem(Melem &elem) { elem.extra(); };
//*Now* we're implementing Icontainer::addElem
};
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.