静态将基础强制转换为派生指针并构造派生成员

时间:2020-01-02 05:37:42

标签: c++ class inheritance casting

我想要的一个最小示例:我有两个课

template<typename T>
struct General;

template<typename T>
struct Specific;

,其中Specific继承自General,但General在其构造函数中调用了Specific成员函数:

template<typename T>
struct Specific: public General<T> {
    int y;
    void compute() { 
        y=x;
        this->x++; 
    }
};

template<typename T>
struct General {
    int x;
    General(int x) : x(x) { static_cast<Specific<T>*>(this)->compute(); };
};

这个想法是,有一个General类,有多个特定类,要使用哪个是在运行时还是编译时决定的。

即使从未实际构建y,以上代码也可以正确编译并运行。我想我摆脱了它,因为它是原始类型,但是如果我使用更复杂的y来代替:

template<typename T>
struct Specific: public General<T> {
    std::vector<int> y;
    void compute() { 
        y={0}; //anything here
        this->x++; 
    }
};

然后代码仍然可以编译,但是在执行带有注释的行时,由于未构建y,因此出现读取访问冲突错误。

有一种解决方法,那就是在General中使用变量y而不是Specific。这种方法有效,但是不同的实现需要不同的变量,并且在General中包含很多仅由一个实现使用的受保护变量并不是很好(尽管从性能的角度来看,我猜编译器会将未使用的成员变量删除为只要可以在编译时检测到正确?)。那么有没有更好的方法呢?

编辑:Scheff建议的一种可能方式:

General(int x) : x(x) { 
    Specific<T> B;
    B = static_cast<Specific<T>&>(*this);
    B.compute();
    *this = static_cast<General<T>&>(B);
}

1 个答案:

答案 0 :(得分:1)

将基类“升级”到派生类不会发生。如果我说

setInterval(function() {
              currentdetik += 1;
              document.getElementById("demo").innerHTML = " [ " + lastURLSegment + " ] Update Terbaru: " +  new Date() + " >> Refresh in : " + (timer - currentdetik)  + " detik";
              if (currentdetik >= timer) {
                    window.location.load();
                    //pelpadam.view.Refresh();
                    //tabpelpadam.load();
                    currentdetik = 0;
                }
            }, 1000);

我要求一个General<int> g(5) ,我会得到一个General<int>General<int>不是Specific<int>,而我得到一个是错误的。确实,由于您的General<int>Specific大,所以构造一个General到期望corrupts the stack的地方std::size(),即使在第一个示例中有两个{{1 }}。

确定要实例化的Specific的哪个子类属于其构造函数句点。到达那里的最明显的方法是将初始化整理为普通的构造函数:

General

并确定要在一个免费函数中实际实例化哪个:

int