简体   繁体   English

运行时数据类型多态

[英]Runtime Datatype polymorphism

I've come up with a solution for runtime polymorphism in C++. 我想出了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. 这里的想法是,编译器将在运行时在switch语句中生成所有模板化类型。 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. 如果我们要在派生类中使用T的参数使用,那么它将不起作用。 So instead we cast the parameters over to T in the derived classs to achieve the desired behavior. 因此,我们将参数强制转换为派生类中的T以实现所需的行为。 I noticed this only works with C-style casting. 我注意到这仅适用于C样式转换。

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. 您的代码完全是100%经典多态的 ,除了一个小的错字:您已经Derived<T>Base 私有继承,而不是公开继承。

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. 这解释了为什么必须使用“ C样式” static_cast转换而不是简单的static_cast从派生类获取其私有基类。 If the base had been public, static_cast would have worked just fine. 如果基础是公开的,那么static_cast会很好地工作。 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. 然后,您的代码就没有什么有趣的了–它只是具有基类和几个派生类的简单“经​​典OOP”。

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. 到您调用虚拟方法时,您肯定还可以:您拥有类型为base*的指针,并且实际上指向了类型为base的对象,因此您可以。 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. UB 可能会进入的唯一地方是您进行C样式转换...但是在这里编译器可以看到,您正在将派生类转换为它的私有基,并且可以完成该工作。 (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 .) (允许C样式的强制转换绕过C ++中的访问控制,但它们仍然遵守其他规则,而不会伪造。它们不会移交给reinterpret_cast 。)

Anyway, this question seems off-topic for CodeReview. 无论如何,对于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 ?". 您应该做的是将主题行发布到StackOverflow,主题行为“在将指针指向Base的指针转换为Derived指针时,为什么需要C样式的强制转换?”。 And the answer is, "You merely forgot to use public inheritance." 答案是:“您只是忘记了使用public继承。”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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