为什么从基数到派生对象的static_cast转换在基数内但不在基数外

问题描述 投票:0回答:2

为什么从基类到派生类的static_case转换可以在基类内部工作,但不能在基类外部工作

class Base
{
public:
    template <typename T>
    int getValue() const { return static_cast<const T&>(*this).getValue(); }
};

class Derived: public Base
{
public:
    Derived(int v): value(v) { }
    int getValue() const { return value; }
    int value;
};

class Another
{
    int getValue() const { return 5; }
};

template <typename T>
void out(const Base & base) {
    cout << base.getValue<T>() << '\n';
}

int main() {
    Derived d(5);
    Base b;
    out<Derived>(d);    //understandable, d has derived part.
    out<Derived>(b);   //don't understand, b is only base.
    out<Another>(b);    //compile time error   
    //static_cast<Derived>(b);   //compile time error
}

我阅读了有关CRTP的this文章,偶然发现了此代码:

template <typename T>
class Base
{
public:
    void doSomething()
    {
        T& derived = static_cast<T&>(*this);
        use derived...
    }
};

class Derived : public Base<Derived>
{
    ...
};

而且我也不太清楚转换在这里是如何工作的。

c++ templates type-conversion static-cast
2个回答
0
投票
之所以有效,是因为在“派生”类型足够完整的地方(即在使用模板的地方),模板代码无效。模板本身不生成任何东西,也不进行编译,仅检查其正确性

仍然,在CRTP中,有些事情是不可能的,例如出于简单的原因,可以在Base类的内部将Derived类的嵌套类型声明用作完整类型:与成员变量和函数不同,它们不完整且不接受正向查找。如果需要这种使用,则必须在Base之前定义第三种类型,包含必需的声明。


0
投票
static_cast转换仅在此转换合法的情况下使用。在您的代码中,您正在创建类Base的对象,并试图将其转换为类Derived。幸运的是,Derived::getValue()的实现不使用任何数据成员,而是从文字中返回一个值。无论如何,这是未定义的行为。

如果是CRTP,则不会创建Base类的实例:仅使用Derived类的实例。

© www.soinside.com 2019 - 2024. All rights reserved.