简体   繁体   中英

Runtime Datatype polymorphism

I've come up with a solution for runtime polymorphism in C++.

#include <iostream>
using namespace std;

class base {
    public:
    virtual void call(double xx) {
        cout << "DERIVED: " << xx << endl;
    }
};

template<typename T>
class derivedT : base {
    public:
    virtual void call(double xx) {
        cout << "DERIVED_T: " << ((T) xx) << endl;
    }
};

int main() {
    base* sample = nullptr;

    cout << "CHOOSE TYPE: (BYTE = 1, UINT = 2, DOUBLE = 3)" << endl;
    uint8_t type = cin.get();
    type -= 48;

    switch (type) {
        case 1:
            sample = (base*) new derivedT<uint8_t>();
        break;
        case 2:
            sample = (base*) new derivedT<uint32_t>();
        break;
        case 3:
            sample = (base*) new derivedT<double_t>();
        break;
    }

    sample->call(2567.45);
    cin.get();
    cin.get();
}

The idea here is that the compiler will generate all of the templated types at run-time in the switch statement. The templates are known at compile time, so now we can then call methods from the base class that are virtual that get overriden in the derived class.

The only reason this works is because the functions of each class have the same parameters. If we were to use parameters in the derived class that use T then it wouldn't work. So instead we cast the parameters over to T in the derived classs to achieve the desired behavior. I noticed this only works with C-style casting.

Soo... what kind of undefined behavior is going on here?

Your code is exactly 100% classical polymorphism , except for one little typo: You have Derived<T> inheriting privately from Base , instead of publicly.

You wrote:

template<typename T>
class derivedT : base {
//               ^ bases, just like members, default to 'private'

You should have written:

template<typename T>
class derivedT : public base {
//               ^^^^^^

This explains why you had to use a "C-style" cast instead of a simple static_cast to get from the derived class up to its private base class. If the base had been public, static_cast would have worked just fine. And then there'd be nothing interesting about your code — it's just a straightforward "classical OOP" with a base class and several derived classes.

Even with the private base, I believe this is not undefined behavior. By the time you're calling the virtual method, you're definitely okay: you have a pointer of type base* , and it actually points to an object of type base , so you're okay. The only place where UB might creep in is where you do the C-style cast... but here the compiler can see that you're casting a derived class to its private base, and will make that work. (C-style casts are allowed to bypass access controls in C++, but they still obey the other rules wrt upcasts. They don't devolve to reinterpret_cast .)

Anyway, this question seems off-topic for CodeReview. What you should have done was post to StackOverflow with the subject line "Why do I need a C-style cast when casting pointer-to- Base to pointer-to- Derived ?". And the answer is, "You merely forgot to use public inheritance."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM