继承的类模板的参数化构造函数

时间:2019-08-07 00:04:55

标签: c++ class templates c++17

我有多个继承的类,但发生错误C2<int (__cdecl *)(int)>': no appropriate default constructor available,但是我为C1,C2定义了参数化构造函数。

一个相关的问题是,我在某些代码中看到标有???的注释行。是什么意思-它正在初始化C2C3的默认构造函数?

#include <iostream>
int y(int) 
{ int a=1; return a } 

template<typename F>
class C1
{
public:
    F f1;
    C1(F g) : f1(g) {}  
};

template<typename F>
class C2 : public C1<F>
{
public:
    F f2;
    C2(F g) : f2(g) {}  
};

template<typename F>
class C3 : public C2<F>
{
public:
    F f3;
    C3(F g) : f3(g) {}
    //C3 (F g) : C2<F>(g) {}        ???
};


int main()
{
    C1 o1(y);
    C2 o2(y);
    C3 o3(y);
}

3 个答案:

答案 0 :(得分:2)

在构造作为另一个类的子类的类时,将调用父级的默认构造函数(除非像标记为???的行那样显式调用另一个构造函数)。但是,看到为每个类都提供了构造函数时,编译器并未生成隐式默认构造函数。因此,当您创建C2的实例时,编译器尝试调用缺少的C1的默认构造函数时,找不到它。

如果您确实提供了默认的构造函数,则可以这样做:

#include <iostream>
int y(int) {
    int a=1;
    return a;
} 

template<typename F>
class C1 {
public:
    F f1{};

    C1() = default;

    C1(F g)
        : f1(g)
    { }  
};

template<typename F>
class C2 : public C1<F>
{
public:
    F f2{};

    C2() = default;

    C2(F g) 
        : f2(g)
    { }  
};

template<typename F>
class C3 : public C2<F>
{
public:
    F f3{};

    C3() = default;

    C3(F g) 
        : f3(g) 
    { }
    //C3 (F g) : C2<F>(g) {}        ???
};


int main()
{
    C1 o1(y);
    C2 o2(y);
    C3 o3(y);
}

标记为???的行调用特定的父构造函数,而不是依赖对父类的默认构造函数的隐式调用。

因此,您可以提供如上所述的默认构造函数,也可以采用???行语法来调用特定的构造函数-这取决于您的类设计和意图。

答案 1 :(得分:1)

正如Sam所说,C2的构造函数正在尝试为C1调用默认的构造函数,该默认构造函数不存在。同样,C3试图调用C2的默认构造函数。

有两个修复程序:

  • C1C2定义默认构造函数,或者:

  • 修改C2的构造函数以调用确实存在的构造函数,如下所示:

    C2(F g) : C1 <F> (g), f2(g) {}

  • 以及类似的C3的构造函数,如下所示:

    C3(F g) : C2 <F> (g), f3(g) {}

我想,这本身就能回答您的第二个问题。

答案 2 :(得分:0)

C2<F>(g)通过调用基类的构造函数来初始化基类。如果您自己不调用构造函数,则编译器将尝试为基类(C2<F>::C2())调用默认构造函数。您的所有类都没有默认构造函数,这是错误的根源。但是实际上您应该做的是自己调用基类的构造函数。

C2(F g) : C1<F>(g), f2(g) {}
C3(F g) : C2<F>(g), f3(g) {}