'virtual static const'

Started by
20 comments, last by Ravyne 11 years, 4 months ago
It frustrates me that I can't declare virtual data members, but anyway...

I have a situation where I have a set of classes that all derive from a virtual base and are used polymorphically. Each derived class matches a specific enum value that I use to control swapping active objects. The thing that's bothering me is that, at present, I have to set the inherited public 'ident' member (of the enumerated type) of each subclass in the constructor. I'd much rather have it as a static const for the class, but in that case I can't use the member polymorphically.

Apart from the disgusting C++ RTTI is there some way to do something like this or am I stuck with the ctor for now?
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
Advertisement
Can you do it with a virtual function that returns `ident'?
Good suggestion. That could definitely make it const, and I'll do that for now, but it would still require setting up a function. I'm wondering if there's some identifiable attribute of a class prior to compile time. Something I could set the enum values by.

Actually, I should probably just think about it more for a while. TBH what I'm thinking of probably just plain isn't there.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
If you don't mind on relying on compiler specific behavior, it is possible, though extremely ugly, to embed data directly in the vtable with some C++ compilers. For MSVC, here's something I wrote when I was really, really bored that looks at single dispatch including with various type code techniques. For the bit about embedding data in the vtable skip down to non-standard approaches.
May I ask why you need to know what the actual type of the object is? If you are going to behave differently depending on the type, that should probably be encoded as a virtual function.

I subscribe to a view that is perhaps a strong version of the Liskov substitution principle: Outside of a factory function, the code should not know about the subtypes of a base class. All you need to do is have virtual functions that describe the entire interface.
The classes in question are scenes. They change a value in a namespace to transfer control. When the namespace's 'update()' function is invoked it checks to see whether its SceneID value matches the one reported by the 'Scene' object it owns. If so it invokes the object's update(). If not then it destroys the object and selects an action based on a switch of the SceneID value (usually spawning a new Scene object).

I bookmarked and will read a link I saw in another thread where someone mentioned state management without a singleton (the namespace in this case is acting like a singleton), so maybe it will become moot.

The primary things I was worried about were the non-const-ness of the Scene::ident member and also the fact that I may forget to initialize it in the ctor, resulting in an annoying error. Álvaro's earlier suggestion solves both those problems. Now it's just the asthetic of it that bothers me. (Why I can't declare a virtual static const data member is beyond me. It doesn't seem like something would be crazy to include in the language.)

I'll definitely check out SiCrane's links there. I don't want to go compiler dependant but that does sound like the kind of extreme-geek stuff I really like to mess with, lol. laugh.png
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
First, I agree with Alvaro -- If you're using inheritance correctly, you should strive to achieve the kind of type transparency he describes. Often times, when you need to know the type of of a derived class from the outside, its because you aren't providing complete functionality via the class interface, or you're violating LSP in some way that you're compensating for.

Second, what is so disgusting about the built-in RTTI facilities compared to this method? You're essentially re-inventing RTTI on your own, I'd stick to the built in unless your platform doesn't support it, you have a good reason to avoid it, or realistic benchmarks show that its a bottleneck.

throw table_exception("(? ???)? ? ???");

Firstly, I am using inheritance correctly. The base class is virtual so LSP doesn't really apply, and since I'm storing the objects by means of a base-class pointer they're obviously using an entirely identical interface.

Secondly, C++ RTTI is flat out disgusting. Just look at std::type_id. I'd much rather just live with the virtual function returning the class' identifying enum value than get involved in that mess. It's not a question of performance. It's a question of not throwing up every time I want to change scenes.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

Firstly, I am using inheritance correctly. The base class is virtual so LSP doesn't really apply

Hmm. I am having an awful lot of trouble getting those three statements to align correctly.

Stephen M. Webb
Professional Free Software Developer


[quote name='Khatharr' timestamp='1354075085' post='5004824']
Firstly, I am using inheritance correctly. The base class is virtual so LSP doesn't really apply

Hmm. I am having an awful lot of trouble getting those three statements to align correctly.
[/quote]

[quote name='Wikipedia']Substitutability is a principle in object-oriented programming. It states that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may be substituted for objects of type T) without altering any of the desirable properties of that program (correctness, task performed, etc.).[/quote]

A virtual class cannot be instantiated.
[source lang="cpp"]class Scene {
public:
virtual ~Scene() {};
virtual int initialize() = 0;
virtual int update() = 0;
SceneID ident;
};
[/source]
If I'm gonna use a derived class from that then it's going to have different functionality.

LSP applies in situations where the base actually has functionality. It requires that inheritors correctly implement the appropriate behavior as the base would.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement