C++ 模板子类调用错误的父构造函数

c++ template subclass calling wrong parent constructor

本文关键字:构造函数 错误 调用 子类 C++      更新时间:2023-10-16

我正在使用Stroustrup的包装模板类:

template<class T, class Pref, class Suf>
class Wrap {
protected: 
    T* p;
    int* owned;
    void incr_owned() { if (owned) ++*owned; }
    void decr_owned() { if (owned && --*owned == 0) { delete p; delete owned; } }
    Pref prefix;
    Suf suffix;
public:
    Wrap(T& x, Pref pr, Suf su)
        :p(&x), owned(0), prefix(pr), suffix(su) { } 
    Wrap(T* pp, Pref pr, Suf su)
        :p(pp), owned(new int(1)), prefix(pr), suffix(su) { } 
    Wrap(const Wrap& a)
        :p(a.p), owned(a.owned), prefix(a.prefix), suffix(a.suffix)
        { incr_owned(); }

我正在对其进行子类化以创建一个线程安全对象:

template<class DSP> class DspWrap : public Wrap<DSP, void(*)(), void(*)()> {
protected:
    CriticalSection* criticalSection;
public:
    DspWrap(DSP& x) : Wrap<DSP, void(*)(), void(*)()>(x, &DspWrap::prefix, &DspWrap::suffix) { 
    }
    DspWrap(DSP* pp) : Wrap<DSP, void(*)(), void(*)()>(pp, &DspWrap::prefix, &DspWrap::suffix) { //compiler error here
    }

但是在创建对象的行中DspWrap<PpmDsp> wrap = DspWrap<PpmDsp>(new PpmDsp());我收到以下错误error C2664: 'Wrap<T,Pref,Suf>::Wrap(T &,Pref,Suf)' : cannot convert parameter 1 from 'PpmDsp *' to 'PpmDsp &'

但是为什么它调用了错误的构造函数?实际上有一个构造函数用于PpmDsp*,那么为什么它试图调用PpmDsp&呢?

提前致谢

我不确定您要将成员初始化为自己做什么时,但是您需要为基类提供适当的构造参数,而基类成员*自己*不是这样做的方法。

一旦我为 prefix 声明了两个函数并suffix其余的函数就可以正常工作并且基构造函数正确初始化。由于我没有您对CriticalSectionDSP的定义,因此我不得不伪造此样本,但是......

#include <iostream>
typedef int CriticalSection;
template<class T, class Pref, class Suf>
class Wrap {
protected:
    T* p;
    int* owned;
    void incr_owned() { if (owned) ++*owned; }
    void decr_owned() { if (owned && --*owned == 0) { delete p; delete owned; } }
    Pref prefix;
    Suf suffix;
public:
    Wrap(T& x, Pref pr, Suf su)
        :p(&x), owned(0), prefix(pr), suffix(su) { }
    Wrap(T* pp, Pref pr, Suf su)
        :p(pp), owned(new int(1)), prefix(pr), suffix(su) { }
};
template<class DSP> class DspWrap : public Wrap<DSP, void(*)(), void(*)()> {
protected:
    CriticalSection* criticalSection;
    // implemenations of these
    static void prefix_fn() {};
    static void suffix_fn() {};
public:
    DspWrap(DSP& x)
        : Wrap<DSP, void(*)(), void(*)()>(x, &prefix_fn, &suffix_fn)
        , criticalSection(new CriticalSection)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    DspWrap(DSP* pp)
        : Wrap<DSP, void(*)(), void(*)()>(pp, &prefix_fn, &suffix_fn)
        , criticalSection(new CriticalSection)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
};
struct MyDSP { };
int main()
{
    MyDSP dsp;
    DspWrap<MyDSP> wrap1(dsp);
    MyDSP *dsp2 = new MyDSP;
    DspWrap<MyDSP> wrap2(dsp2);
    return 0;
}

输出

DspWrap<MyDSP>::DspWrap(DSP &) [DSP = MyDSP]
DspWrap<MyDSP>::DspWrap(DSP *) [DSP = MyDSP]

&DspWrap::prefix的类型为 Pref* 。你把它传递给 Wrap 的构造器,它需要一个类型 Pref 的对象。相反,传递DspWrap::prefix在语法上是正确的。

然而,DspWrap::prefix在传递给Wrap的构造函数时还没有初始化,所以实际上在之后调用Wrap::prefix有未定义的行为。