I have classes like this:
class ParkingLot
{
public:
int spaces;
virtual bool something() { return true; }
}
class ParkingLotBuilding
{
public:
ParkingLot Floor1, Floor2;
}
I've got a whole lot of functions that take ParkingLotBuilding. Let's say someone (me) derives from ParkingLot and ParkingLotBuilding:
class DerivedParkingLot : public ParkingLot
{
public:
virtual bool something() { return false; }
}
class DerivedParkingLotBuilding : public ParkingLotBuilding
{
public:
// how can I make it so that Floor1 and Floor2 are for DerivedParkingLot?
}
I've got functions I don't control that are like this:
CheckBuilding( ParkingLotBuilding &building )
{
if(building.Floor1.something() == true)
// error
}
If I pass a DerivedParkingLotBuilding object to that function how do I make it so that it calls DerivedParkingLot::something() to return false? Is that possible? Sorry if I didn't explain this right I'm not sure how to ask about the problem. Thanks
As JohnSmith pointed out, you can't override data members, just member functions. Since ParkingLotBuilding contains ParkingLot values, and not ParkingLot pointers or references, they can't be used polymorphically, even in DerivedParkingLot. (That's just how C++ works: only pointers and references can have a dynamic type.)
That means that if you can't change the ParkingLotBuilding class (or the CheckBuilding function), then you're stuck. There is no deriving you can do that will get the CheckBuilding function to operate on a DerivedParkingLot object.
The moral of this story is that classes must be designed for inheritance from the beginning.
In fact you just to call the DerivedParkingLot function from a ParkingLot instance ?
Your code already did it by specifiying the something method as virtual, it will automaticaly search for the lowest method in his inherited tree.
A simple way to test it is to implement the something method in ParkingLot and DerivedParkingLot, put different message in each and check it
One way you might be able to approach this is by making ParkingLot a template class.
template<typename T>
class ParkingLotBuilding
{
public:
T Floor1, Floor2;
}
Then when creating a ParkingLotBuilding, you could use these types:
ParkingLotBuilding<ParkingLot>
ParkingLotBuilding<DerivedParkingLot>
Also if you don't like templating all the time and want to just use ParkingLotBuilding and DerivedParkingLotBuilding, you could rename the class to something like Building and use typedefs:
typedef Building<ParkingLot> ParkingLotBuilding
typedef Building<DerivedParkingLot> DerivedParkingLotBuilding
This approach isn't exactly inheritance between the ParkingLotBuilding types (and may not be the best approach - I've never seen this before), but it might do what you need.
In your example, Floor1 has no way of knowing whether it was instantiated inside of ParkingLotBuilding or DerivedParkingLotBuilding.
You could use RTTI to deal with this something like:
CheckBuilding (ParkingLotBuilding *building)
{
if (dynamic_cast<DerivedParkingLogBuilding*>(building))
{
// Floor is in a derived parking log building
}
else
{
// Floor is in a parking lot building
}
}
Not exactly the best was of doing this though, as pointed out above.
Related
I came across an open source C++ code and I got curious, why do people design the classes this way?
So first things first, here is the Abstract class:
class BaseMapServer
{
public:
virtual ~BaseMapServer(){}
virtual void LoadMapInfoFromFile(const std::string &file_name) = 0;
virtual void LoadMapFromFile(const std::string &map_name) = 0;
virtual void PublishMap() = 0;
virtual void SetMap() = 0;
virtual void ConnectROS() = 0;
};
Nothing special here and having an abstract class can have several well understood reasons. So from this point, I thought maybe author wanted to share common features among other classes. So here is the next class, which is a seperate class but actually holds a pointer of type abstract class mentioned above (actual cpp file, other two classes are header files) :
class MapFactory
{
BaseMapServer *CreateMap(
const std::string &map_type,
rclcpp::Node::SharedPtr node, const std::string &file_name)
{
if (map_type == "occupancy") return new OccGridServer(node, file_name);
else
{
RCLCPP_ERROR(node->get_logger(), "map_factory.cpp 15: Cannot load map %s of type %s", file_name.c_str(), map_type.c_str());
throw std::runtime_error("Map type not supported")
}
}
};
And now the interesting thing comes, here is the child class of the abstract class:
class OccGridServer : public BaseMapServer
{
public:
explicit OccGridServer(rclcpp::Node::SharedPtr node) : node_(node) {}
OccGridServer(rclcpp::Node::SharedPtr node, std::string file_name);
OccGridServer(){}
~OccGridServer(){}
virtual void LoadMapInfoFromFile(const std::string &file_name);
virtual void LoadMapFromFile(const std::string &map_name);
virtual void PublishMap();
virtual void SetMap();
virtual void ConnectROS();
protected:
enum MapMode { TRINARY, SCALE, RAW };
// Info got from the YAML file
double origin_[3];
int negate_;
double occ_th_;
double free_th_;
double res_;
MapMode mode_ = TRINARY;
std::string frame_id_ = "map";
std::string map_name_;
// In order to do ROS2 stuff like creating a service we need a node:
rclcpp::Node::SharedPtr node_;
// A service to provide the occupancy grid map and the message with response:
rclcpp::Service<nav_msgs::srv::GetMap>::SharedPtr occ_service_;
nav_msgs::msg::OccupancyGrid map_msg_;
// Publish map periodically for the ROS1 via bridge:
rclcpp::TimerBase::SharedPtr timer_;
};
So what is the purpose of the MapFactory class?
To be more specific - what is the advantage of creating a class which holds a pointer of type Abstract class BaseMapServer which is a constructor (I believe) and this weird constructor creates a memory for the new object called OccGridServer and returns it? I got so confused by only writing this. I really want to become a better C++ coder and I am desperate to know the secret behind these code designs.
The MapFactory class is used to create the correct subclass instance of BaseMapServer based on the parameters passed to it.
In this particular case there is only one child class instance, but perhaps there are plans to add more. Then when more are added the factory method can look something like this:
BaseMapServer *CreateMap(
const std::string &map_type,
rclcpp::Node::SharedPtr node, const std::string &file_name)
{
if (map_type == "occupancy") return new OccGridServer(node, file_name);
// create Type2Server
else if (map_type == "type2") return new Type2Server(node, file_name);
// create Type3Server
else if (map_type == "type3") return new Type3Server(node, file_name);
else
{
RCLCPP_ERROR(node->get_logger(),
"map_factory.cpp 15: Cannot load map %s of type %s",
file_name.c_str(), map_type.c_str());
throw std::runtime_error("Map type not supported")
}
}
This has the advantage that the caller doesn't need to know the exact subclass being used, and in fact the underlying subclass could potentially change or even be replaced under the hood without the calling code needing to be modified. The factory method internalizes this logic for you.
Its a Factory pattern. See https://en.wikipedia.org/wiki/Factory_method_pattern. It looks like the current code only supports one implementation (OccGridServer), but more could be added at a future date. Conversely, if there's only ever likely to be one concrete implementation, then it's overdesign.
This is example of the factory design pattern. The use case is this: there are several types of very similar classes that will be used in code. In this case, OccGridServer is the only one actually shown, but a generic explanation might reference hypothetical Dog, Cat, Otter, etc. classes. Because of their similarity, some polymorphism is desired: if they all inherit from a base class Animal they can share virtual class methods like ::genus, ::species, etc., and the derived classes can be pointed to or referred to with base class pointers/references. In your case, OccGridServer inherits from BaseMapServer; presumably there are other derived classes as well, and pointers/references.
If you know which derived class is needed at compile time, you would normally just call its constructor. The point of the factory design pattern is to simplify selection of a derived class when the particular derived class is not known until runtime. Imagine that a user picks their favorite animal by selecting a button or typing in a name. This generally means that somewhere there's a big if/else block that maps from some type of I/O disambiguator (string, enum, etc.) to a particular derived class type, calling its constructor. It's useful to encapsulate this in a factory pattern, which can act like a named constructor that takes this disambiguator as a "constructor" parameter and finds the correct derived class to construct.
Typically, by the way, CreateMap would be a static method of BaseMapServer. I don't see why a separate class for the factory function is needed in this case.
I am starting to code bigger objects, having other objects inside them.
Sometimes, I need to be able to call methods of a sub-object from outside the class of the object containing it, from the main() function for example.
So far I was using getters and setters as I learned.
This would give something like the following code:
class Object {
public:
bool Object::SetSubMode(int mode);
int Object::GetSubMode();
private:
SubObject subObject;
};
class SubObject {
public:
bool SubObject::SetMode(int mode);
int SubObject::GetMode();
private:
int m_mode(0);
};
bool Object::SetSubMode(int mode) { return subObject.SetMode(mode); }
int Object::GetSubMode() { return subObject.GetMode(); }
bool SubObject::SetMode(int mode) { m_mode = mode; return true; }
int SubObject::GetMode() { return m_mode; }
This feels very sub-optimal, forces me to write (ugly) code for every method that needs to be accessible from outside. I would like to be able to do something as simple as Object->SubObject->Method(param);
I thought of a simple solution: putting the sub-object as public in my object.
This way I should be able to simply access its methods from outside.
The problem is that when I learned object oriented programming, I was told that putting anything in public besides methods was blasphemy and I do not want to start taking bad coding habits.
Another solution I came across during my research before posting here is to add a public pointer to the sub-object perhaps?
How can I access a sub-object's methods in a neat way?
Is it allowed / a good practice to put an object inside a class as public to access its methods? How to do without that otherwise?
Thank you very much for your help on this.
The problem with both a pointer and public member object is you've just removed the information hiding. Your code is now more brittle because it all "knows" that you've implemented object Car with 4 object Wheel members. Instead of calling a Car function that hides the details like this:
Car->SetRPM(200); // hiding
You want to directly start spinning the Wheels like this:
Car.wheel_1.SetRPM(200); // not hiding! and brittle!
Car.wheel_2.SetRPM(200);
And what if you change the internals of the class? The above might now be broken and need to be changed to:
Car.wheel[0].SetRPM(200); // not hiding!
Car.wheel[1].SetRPM(200);
Also, for your Car you can say SetRPM() and the class figures out whether it is front wheel drive, rear wheel drive, or all wheel drive. If you talk to the wheel members directly that implementation detail is no longer hidden.
Sometimes you do need direct access to a class's members, but one goal in creating the class was to encapsulate and hide implementation details from the caller.
Note that you can have Set and Get operations that update more than one bit of member data in the class, but ideally those operations make sense for the Car itself and not specific member objects.
I was told that putting anything in public besides methods was blasphemy
Blanket statements like this are dangerous; There are pros and cons to each style that you must take into consideration, but an outright ban on public members is a bad idea IMO.
The main problem with having public members is that it exposes implementation details that might be better hidden. For example, let's say you are writing some library:
struct A {
struct B {
void foo() {...}
};
B b;
};
A a;
a.b.foo();
Now a few years down you decide that you want to change the behavior of A depending on the context; maybe you want to make it run differently in a test environment, maybe you want to load from a different data source, etc.. Heck, maybe you just decide the name of the member b is not descriptive enough. But because b is public, you can't change the behavior of A without breaking client code.
struct A {
struct B {
void foo() {...}
};
struct C {
void foo() {...}
};
B b;
C c;
};
A a;
a.c.foo(); // Uh oh, everywhere that uses b needs to change!
Now if you were to let A wrap the implementation:
class A {
public:
foo() {
if (TESTING) {
b.foo();
} else {
c.foo();
}
private:
struct B {
void foo() {...}
};
struct C {
void foo() {...}
};
B b;
C c;
};
A a;
a.foo(); // I don't care how foo is implemented, it just works
(This is not a perfect example, but you get the idea.)
Of course, the disadvantage here is that it requires a lot of extra boilerplate, like you have already noticed. So basically, the question is "do you expect the implementation details to change in the future, and if so, will it cost more to add boilerplate now, or to refactor every call later?" And if you are writing a library used by external users, then "refactor every call" turns into "break all client code and force them to refactor", which will make a lot of people very upset.
Of course instead of writing forwarding functions for each function in SubObject, you could just add a getter for subObject:
const SubObject& getSubObject() { return subObject; }
// ...
object.getSubObject().setMode(0);
Which suffers from some of the same problems as above, although it is a bit easier to work around because the SubObject interface is not necessarily tied to the implementation.
All that said, I think there are certainly times where public members are the correct choice. For example, simple structs whose primary purpose is to act as the input for another function, or who just get a bundle of data from point A to point B. Sometimes all that boilerplate is really overkill.
I have a base class representing an item with some common properties (name, a few flags, etc):
class AbstractItem;
class MacroDefinition : public AbstractItem;
I also have a templatized class which manages collections of these items, also taking care of common functionality like loading them from XML files on disk:
template <class ItemT>
class AbstractItemManager
{
public:
AbstractItemManager();
ItemT* GetAt(int index);
vector<ItemT*> Get(...);
private:
vector<ItemT*> mItems;
};
For any given type of AbstractItem, I can create a manager class of that appropriate type, have the base functionality handled for me, and then layer functionality specific to that type on top of that:
class MacroManager : public AbstractItemManager<MacroDefinition>
{
public:
MacroManager():AbstractItemManager<MacroDefinition>();
};
The fact that the manager class takes the type of item as a template parameter means I can make calls like this, both within MacroManager and externally, and get items of the appropriate type without having to blindly cast pointers all over the place.
MacroManager* macroManager = new MacroManager();
Macro* macro = macroManager->GetAt(2);
Now I'm implementing another class. I want to be able to pass it a reference to an AbstractItemManager so that I can access the list of items in any given manager class. However, I need to make the compiler understand that ItemT will always be derived from AbstractItem. I'd like to be able to do something like this:
class FavoriteAbstractItemList
{
public:
FavoriteAbstractItemList(AbstractItemManager* manager)
:mManager(manager)
{
vector<AbstractItem*> items = mManager->Get(...);
...
}
private:
AbstractItemManager* mManager;
};
Consequently:
FavoriteAbstractItemList* list = new FavoriteAbstractItemList(macroManager);
Of course, this is invalid, because I'm not supplying a template argument to AbstractItemManager when I'm using it in FavoriteAbstractItemList. Because my manager subclasses (MacroManager etc.) have all different ItemT types, I'm stuck here.
I imagine that I could change my class hierarchy a bit, and this would work:
template<class ItemT>
class AbstractItemManager_Base;
class AbstractItemManager : public AbstractItemManager_Base<AbstractItem>;
class MacroManager : public AbstractItemManager;
But then the template argument ItemT would be set in stone as AbstractItem in MacroManager etc., so I'd have to explicitly cast all items within MacroManager to Macro and take care to ensure that only items of type Macro were be added to it.
This seems like it's probably a common problem, but not one that has a straightforward answer. I don't have too much hands-on experience with C++ templates, so I'd greatly appreciate being set straight on this issue. Given the tradeoffs I've presented, what's the most sensible way to accomplish what I'm looking for? Or am I approaching things the wrong way to begin with?
Thanks for all your helpful answers. I ended up going with the solution that you both proposed. It hadn't occurred to me that I could use a template type to override an already-defined base type, but the compile-time chicanery of C++ templates is something I'm slowly getting used to.
As for the vector problem, that's unfortunate, but I ended up going with one of the proposed solutions and creating a separate method in the templatized class that calls the original method and stuffs everything into a new vector<ItemT*> with a bunch of static casts. I'm sure that adds a little bit of overhead, but it's still far more elegant than my knee-jerk solution of abandoning templates entirely. The only thing I really lose is the ability to directly iterate over mItems in subclasses without a cast from AbstractItem* to Macro* (etc.), but I can certainly deal with that.
Here's the new class hierarchy, in essence:
class AbstractItemManager
{
public:
virtual AbstractItem* GetAt(int index);
vector<AbstractItem*> Get(...);
protected:
vector<AbstractItem*> mItems;
};
template <class ItemT>
class TemplatizedItemManager : public AbstractItemManager
{
public:
virtual ItemT* GetAt(int index);
std::vector<ItemT*> GetItems(...);
};
class MacroManager : public TemplatizedItemManager<Macro>;
Thanks again!
class AbstractItemManager_Base
{
public:
virtual AbstractItem* GetAt (int index) = 0;
};
template <class ItemT>
class AbstractItemManager : public AbstractItemManager_Base
{
ItemT* GetAt (int index); // works if ItemT derives from AbstractItem
};
Now you can use an AbstractItemManager_Base in FavoriteAbstractItemList.
Replacing vector<ItemT*> Get(...) is somewhat more involved. vector<AbstractItem*> is not compatible with vector<ItemT*>, for any ItemT. You can try to create your own container hierarchy, such that myvector<AbstractItem*> is somehow compatible with myvector<ItemT*>; or provide an iterator-based interface to your ItemManager so that it is a container; or just have two separate unrelated functions, one returning vector<ItemT*> and the other returning vector<AbstractItem*>.
You actually have two problems. The first one is aboutz GetAt. This has a simple solution: Don't template the base, template the derived:
class AbstractItem
{
// ...
};
class MacroDefintiion:
public AbstractItem
{
// ...
};
class AbstractItemMananger
{
public:
virtual AbstractItem* GetAt(int) = 0;
// ...
};
template<typename Item> class SpecificAbstractItemManager
{
public:
Item* GetAt(); // covariant return type
// ...
};
class MacroManager: public SpecificAbstractItemManager
{
// ...
};
The second one is your Get method. That one is problematic because std::vector<Derived*> and std::vector<Base*> are unrelated classes, as far as C++ is concerned, and therefore you cannot use them for covariant return types.
Probably the best solution here is to have two functions in the derived class, one returning a std::vector<AbstractItem> (inherited from and overriding the base class function) and another one returning an std::vector<Item*>.
That is, in AbstractItemManager you have
std::vector<AbstractItem*> Get() = 0;
and in SpecificAbstractItemManager<Item> you have e.g.
std::vector<AbstractItem*> Get() { return GetSpecific(); }
std::vector<Item*> GetSpecific();
I have a simple, low-level container class that is used by a more high-level file class. Basically, the file class uses the container to store modifications locally before saving a final version to an actual file. Some of the methods, therefore, carry directly over from the container class to the file class. (For example, Resize().)
I've just been defining the methods in the file class to call their container class variants. For example:
void FileClass::Foo()
{
ContainerMember.Foo();
}
This is, however, growing to be a nuisance. Is there a better way to do this?
Here's a simplified example:
class MyContainer
{
// ...
public:
void Foo()
{
// This function directly handles the object's
// member variables.
}
}
class MyClass
{
MyContainer Member;
public:
void Foo()
{
Member.Foo();
// This seems to be pointless re-implementation, and it's
// inconvenient to keep MyContainer's methods and MyClass's
// wrappers for those methods synchronized.
}
}
Well, why not just inherit privatly from MyContainer and expose those functions that you want to just forward with a using declaration? That is called "Implementing MyClass in terms of MyContainer.
class MyContainer
{
public:
void Foo()
{
// This function directly handles the object's
// member variables.
}
void Bar(){
// ...
}
}
class MyClass : private MyContainer
{
public:
using MyContainer::Foo;
// would hide MyContainer::Bar
void Bar(){
// ...
MyContainer::Bar();
// ...
}
}
Now the "outside" will be able to directly call Foo, while Bar is only accessible inside of MyClass. If you now make a function with the same name, it hides the base function and you can wrap base functions like that. Of course, you now need to fully qualify the call to the base function, or you'll go into an endless recursion.
Additionally, if you want to allow (non-polymorphical) subclassing of MyClass, than this is one of the rare places, were protected inheritence is actually useful:
class MyClass : protected MyContainer{
// all stays the same, subclasses are also allowed to call the MyContainer functions
};
Non-polymorphical if your MyClass has no virtual destructor.
Yes, maintaining a proxy class like this is very annoying. Your IDE might have some tools to make it a little easier. Or you might be able to download an IDE add-on.
But it isn't usually very difficult unless you need to support dozens of functions and overrides and templates.
I usually write them like:
void Foo() { return Member.Foo(); }
int Bar(int x) { return Member.Bar(x); }
It's nice and symmetrical. C++ lets you return void values in void functions because that makes templates work better. But you can use the same thing to make other code prettier.
That's delegation inheritance and I don't know that C++ offers any mechanism to help with that.
Consider what makes sense in your case - composition (has a) or inheritance (is a) relationship between MyClass and MyContainer.
If you don't want to have code like this anymore, you are pretty much restricted to implementation inheritance (MyContainer as a base/abstract base class). However you have to make sure this actually makes sense in your application, and you are not inheriting purely for the implementation (inheritance for implementation is bad).
If in doubt, what you have is probably fine.
EDIT: I'm more used to thinking in Java/C# and overlooked the fact that C++ has the greater inheritance flexibility Xeo utilizes in his answer. That just feels like nice solution in this case.
This feature that you need to write large amounts of code is actually necessary feature. C++ is verbose language, and if you try to avoid writing code with c++, your design will never be very good.
But the real problem with this question is that the class has no behaviour. It's just a wrapper which does nothing. Every class needs to do something other than just pass data around.
The key thing is that every class has correct interface. This requirement makes it necessary to write forwarding functions. The main purpose of each member function is to distribute the work required to all data members. If you only have one data member, and you've not decided yet what the class is supposed to do, then all you have is forwarding functions. Once you add more member objects and decide what the class is supposed to do, then your forwarding functions will change to something more reasonable.
One thing which will help with this is to keep your classes small. If the interface is small, each proxy class will only have small interface and the interface will not change very often.
I would like to define as class X with a static method:
class X
{
static string get_type () {return "X";}
//other virtual methods
}
I would like to force classes which inherit from X to redefine the get_type() method
and return strings different from "X" (I am happy if they just redefine get_type for now).
How do I do this? I know that I cannot have virtual static methods.
Edit: The question is not about the type_id, but in general about a static method that
should be overriden. For example
class X {
static int getid() {return 1;}
}
template<int id>
class X {
public:
static int getid() { return id; }
};
class Y : public X<2> {
};
You haven't overridden the method, but you've forced every subclass to provide an ID. Caveat: I haven't tried this, there might be some subtle reason why it wouldn't work.
If I'm not mistaken, to call the static method, you have to invoke the method by specifying the exact name of the class, e.g X::get_type();, DerivedClass::get_type() etc and in any case, if called on an object, the dynamic type of the object is not taken into account. So at least in the particular case, it will probably only be useful in a templated context when you are not expecting polymorphic behavior.
However, I don't see why it shouldn't be possible to force each interesting class (inherited or not, since "compile-time polymorphism" doesn't care) to provide this functionality with templates. In the following case, you must specialize the get_type function or you'll have a compile-time error:
#include <string>
struct X {};
struct Derived: X {};
template <class T> std::string get_type() {
static_assert(sizeof(T) == 0, "get_type not specialized for given type");
return std::string();
}
template <> std::string get_type<X>() {
return "X";
}
int main() {
get_type<X>();
get_type<Derived>(); //error
}
(static_assert is C++0x, otherwise use your favourite implementation, e.g BOOST_STATIC_ASSERT. And if you feel bad about specializing functions, specialize a struct instead. And if you want to force an error if someone accidentally tries to specialize it for types not derived from X, then that should also be possible with type_traits.)
I'd say you know the why but just in case here's a good explanation:
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/cplr139.htm
It looks like your going to have to design your way out of this. Perhaps a virtual function that wraps a Singleton?
Don't do that, use typeid instead.
To make a long story short, you can't do it. The only way to require a derived class to override a base class function is to make it a pure virtual (which can't be static).
You can't do this for a number of reasons. You can't define the function in X and have it be pure virtual. You can't have virtual static functions at all.
Why must they be static?
Here you go
class X
{
static string get_type() {return "X"; }
};
class Y : public X
{
static string get_type() {return "Y"; }
};
The code above does exactly what you requested: the derived class redefines get_type and returns a different string. If this is not what you want, you have to explain why. You have to explain what is it you are trying to do and what behavior you expect from that static method. If is absolutely unclear form your original question.
You mention a few places about guaranteeing that the child types yield unique values for your function. This is, as others have said, impossible at compile time [at least, without the use of templates, which might or might not be acceptable]. But if you delay it until runtime, you can maybe pull something similar off.
class Base {
static std::vector<std::pair<const std::type_info*, int> > datas;
typedef std::vector<std::pair<const std::type_info*, int> >::iterator iterator;
public:
virtual ~Base() { }
int Data() const {
const std::type_info& info = typeid(*this);
for(iterator i = datas.begin(); i != datas.end(); ++i)
if(*(i->first) == info) return i->second;
throw "Unregistered Type";
}
static bool RegisterClass(const Base& p, int data) {
const std::type_info& info = typeid(p);
for(iterator i = datas.begin(); i != datas.end(); ++i) {
if(i->second == data) {
if(*(i->first) != info) throw "Duplicate Data";
return true;
}
if(*(i->first) == info) throw "Reregistering";
}
datas.push_back(std::make_pair(&info, data));
return true;
}
};
std::vector<std::pair<const std::type_info*, int> > Base::datas;
class Derived : public Base { };
const DerivedRegisterFlag = Base::RegisterClass(Derived(), 10);
class OtherDerived : public Base { };
const OtherDerivedRegisterFlag = Base::RegisterClass(OtherDerived(), 10); //exception
Caveats: This is completely untested. The exceptions would get thrown before entering main if you do it this way. You could move the registration into constructors, and accept the per-instance overhead of registration checking if you'd rather.
I chose an unordered vector for simplicity; I'm not sure if type_info::before provides the necessary semantics to be used as a predicate for a map, and presumably you won't have so many derived classes that a linear search would be problematic anyhow. I store a pointer because you can't copy type_info objects directly. This is mostly safe, since the lifetime of the object returned by typeid is the entire program. There might be issues when the program is shutting down, I'm not sure.
I made no attempt to protect against static order of initialization errors. As written, this will fail at some point.
Finally, no it isn't static, but "static" and "virtual" don't really make sense together anyhow. If you don't have an instance of the type to act on, then how do you know which overwritten method to chose? There are a few cases with templates where you might legitimately want to call a static method without an actual object, but that's not likely to be common.
*edit: Also, I'm not sure how this interacts with dynamically linked libraries and the like. My suspicion is that RTTI is unreliable in those situations, so obviously this is similarly unreliable.
Use Delphi, it supports virtual static members on classes. ;>
Apologies for resurrecting this thread, but I've just encountered this moral crisis as well. This is a very bold and possibly foolish statement to make, but I wholeheartedly disagree with what most people are saying about static virtual not making any sense. This dilemma stems from how static members are commonly used versus what they're actually doing underneath.
People often express facts using static classes and/or members - something that is true for all instances if instances are relevant, or simply facts about the world in the case of static classes. Suppose you're modelling a Philosophy class. You might define abstract class Theory to represent a theory which is to be taught, then inherit from Theory in TheoryOfSelf, TheoryOfMind and so on. To teach a Theory, you'd really want a method called express() which expresses a theory using a particular turn of phrase appropriate to the audience. One would assume that any inheriting class should expose an identical method express(). If I were able to, I would model this relationship using static virtual Theory.express() - it is both a statement of fact transcending the concept of instances (therefore static) and nonspecific, requiring a specific implementation by each type of theory (therefore virtual).
I completely agree however with people justifying the prohibition on the grounds of what static is actually doing - it makes perfect sense in terms of coding principles, the issue arises from the customary ways people commonly model the real world.
The best resolution to this problem I've been able to think of is to model Theory as a singleton instead - there may be an instance of a theory, but there's only ever one of them. If you want an alternative, it's a different type, so create a new derived class. To me this approach just seems arbitrary and introduces unnecessary noise.