I wanted to see if it's possible to create "interfaces", inherit them, and then check at runtime if any random class implements that interface. This is what I have:
struct GameObject {
int x,y;
std::string name;
virtual void blah() { };
};
struct Airholder {
int oxygen;
int nitrogen;
};
struct Turf : public GameObject, public Airholder {
Turf() : GameObject() {
name = "Turf";
}
void blah() { };
};
void remove_air(GameObject* o) {
Airholder* a = dynamic_cast<Airholder*>(o);
if(!a) return;
a->oxygen = 0;
a->nitrogen = 0;
};
Now, it works. The documentation says that it works, the test example works.. But also, it didn't compile until I added a virtual method to GameObject. The thing is, I really don't know if the feature is intended to be used like that. What made me wonder there is the fact that I have to declare a virtual function for the class I'm checking. But obviously, there is none, the class I'm checking itself has no virtual functions, in fact my whole code has nothing to do with virtual functions, it's an entirely different approach.
So, I guess my question is: If what I'm doing really works, why do I need a virtual function to give my class a vtable? Why can't I declare the class a "runtime type" or something without virtual functions?
This cast is used for handling polymorphism. You only need to use it when you're casting to a derived class. This is exclusively to be used in inheritence when you cast from base class to derived class.
Multiple Inheritance is a feature of C++ where a class can inherit from more than one classes. The constructors of inherited classes are called in the same order in which they are inherited.
The reason behind this is to prevent ambiguity. Consider a case where class B extends class A and Class C and both class A and C have the same method display(). Now java compiler cannot decide, which display method it should inherit. To prevent such situation, multiple inheritances is not allowed in java.
Allowing multiple inheritance makes the rules about function overloads and virtual dispatch decidedly more tricky, as well as the language implementation around object layouts. These impact language designers/implementors quite a bit and raise the already high bar to get a language done, stable, and adopted.
§ 5.2.7 of the standard says:
If T is “pointer to cv1 B” and v has type “pointer to cv2 D” such that B is a base class of D, the result is a pointer to the unique B sub-object of the D object pointed to by v. Similarly, if T is “reference to cv1 B” and v has type “cv2 D” such that B is a base class of D, the result is an lvalue for the unique60) B sub-object of the D object referred to by v. In both the pointer and reference cases, cv1 shall be the same cvqualification as, or greater cv-qualification than, cv2, and B shall be an accessible unambiguous base class of D. [Example:
struct B {};
struct D : B {};
void foo(D* dp)
{
B* bp = dynamic_cast(dp); // equivalent to B* bp = dp;
}
—end example]
And to make a type polymorphic, it needs a virtual function, as per § 10.3:
Virtual functions support dynamic binding and object-oriented programming. A class that declares or inherits a virtual function is called a polymorphic class.
So the reason why is "because the standard says so." That doesn't really tell you why the standard says so though, but the other answers cover that well I think.
So, I guess my question is: If what I'm doing really works, why do I need a virtual function to give my class a vtable? Why can't I declare the class a "runtime type" or something without virtual functions?
The presence of a virtual function is what makes a class polymorphic in C++. dynamic_cast<>
only works with polymorphic classes. (The compiler will reject a dynamic cast on a non-polymorphic object.)
Polymorphism has a cost, both in time and in space (memory). Calls to virtual functions are now indirect, typically implemented in terms of a virtual table. In some critical places, those costs are simply unacceptable. So the language provides means of avoiding these costs.
Similar concepts exist elsewhere in the language. The underlying principle is that if you don't want to use some high-falutin' feature you shouldn't have to pay for the fact the some people do want to use it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With