【问题标题】:How to cast if is derived class from a specific base class如果是来自特定基类的派生类,如何强制转换
【发布时间】:2019-04-10 04:21:36
【问题描述】:

我正在尝试将一个对象转换为类,如果它是从另一个特定类派生的,还是在模板方法中转换为基本类型(int、float string 等),但我得到了同样的错误。

代码:

#include <string>
#include <iostream>

//Base class
class A
{
public:
    virtual ~A() = default;
    std::string Get() {
        return "A";
    };
};

//Derived class
class B : public A
{
public:
    virtual ~B() = default;
    std::string Get() {
        return "B";
    };
};

class C
{
public:
    template <typename T>
    void Echo(T* t)
    {
        if (std::is_base_of<A, T>::value)
        {
            //complex types, derived from A
            std::cout << dynamic_cast<A*>(t)->Get();
        }
        else
        {
            //basic types(int, float, string etc...)
            std::cout << *t;
        }
    }
};

int main()
{
    C c;
    c.Echo(new int(12345));
    c.Echo(new B());

    return 0;
}

错误:

error: cannot dynamic_cast ‘t’ (of type ‘int*’) to type ‘class A*’ (source is not a pointer to class)
error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘B’)
.
.
.

有没有人知道如何做这样的事情,谢谢?

【问题讨论】:

    标签: c++ templates inheritance casting


    【解决方案1】:

    如果 constexpr:你想使用 C++17:

        if constexpr(std::is_base_of<A, T>::value)
        {
            //complex types, derived from A
            std::cout << static_cast<A*>(t)->Get();
        }
        else
        {
            //basic types(int, float, string etc...)
            std::cout << *t;
        }
    

    问题在于,即使您在编译时知道 T 是 int*,经典的 if 仍将评估所有分支。

    另一个选项是使用std::enable_if,例如:

    template <typename T>
    std::enable_if<std::is_base_of<A, T>::value, void> Echo(T* t)
    {
        std::cout << dynamic_cast<A*>(t)->Get();
    }
    

    其他分支也类似。

    在评论之后,您确实知道TA,所以请使用static_cast

    【讨论】:

    • 如果您知道类型可以在运行时正确转换,为什么还要使用动态转换?使用static_cast
    • 嗯,一个原因:static_cast 不能很好地处理虚拟基类,因为它们相对于派生类的位置在编译时是未知的。这不适用于这里...
    猜你喜欢
    • 2014-11-23
    • 2015-03-27
    • 1970-01-01
    • 2015-05-29
    • 2011-04-06
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 2019-11-13
    相关资源
    最近更新 更多