关于C++:用模板和构造函数从两个派生类中继承多个继承

Multiple Inheritance from two derived classes with templates and constructors

我从这里开始遵循这个例子,但是我使用模板并调用一个派生类的构造函数。以下代码在没有模板的情况下工作,但如果包含模板,我不确定为什么会出现以下错误:

1
2
3
: error: no matching function for call to ‘AbsInit<double>::AbsInit()
     NotAbsTotal(int x) : AbsInit(x) {};
                                   ^

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

using namespace std;

template<typename T>
class AbsBase
{
    virtual void init() = 0;
    virtual void work() = 0;
};

template<typename T>
class AbsInit : public virtual AbsBase<T>
{
public:
    int n;
    AbsInit(int x)
    {
        n = x;
    }
    void init() {  }
};

template<typename T>
class AbsWork : public virtual AbsBase<T>
{
    void work() {  }
};

template<typename T>
class NotAbsTotal : public AbsInit<T>, public AbsWork<T>
{
public:
    T y;
    NotAbsTotal(int x) : AbsInit(x) {};
};    // Nothing, both should be defined


int main() {
  NotAbsTotal<double> foo(10);
  cout << foo.n << endl;

}


在下面的代码段中…

1
2
3
4
5
template<typename T>
class NotAbsTotal : public AbsInit<T>
{
    NotAbsTotal(int x) : AbsInit(x) {}
};

AbsInit是一个依赖的基类:

A dependent base class is a base class that is a dependent type and is not the current instantiation.

…并试图使用不合格的注入类名(AbsInit)来引用,但:

The injected-class-name of a class (Clause [class]) is also considered to be a member of that class for the purposes of name hiding and lookup.

…但是,[温度差]/p3:

In the definition of a class or class template, the scope of a dependent base class ([temp.dep.type]) is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [ Example:

1
2
3
4
5
6
7
typedef double A;
template<class T> class B {
  typedef int A;
};
template<class T> struct X : B<T> {
  A a;              // a has type double
};

[...]

— end example ]

因此,AbsInit不能绑定到存在于AbsInit本身范围内的注入类名。该名称将接受非限定名称查找,并引用在全局命名空间中找到的类模板。

为避免错误或强制执行所需的名称解析,请将模板参数列表附加到类模板名称AbsInit中:

1
2
NotAbsTotal(int x) : AbsInit<T>(x) {}
//                          ~~^

或者使用限定名:

1
2
NotAbsTotal(int x) : NotAbsTotal::AbsInit(x) {}
//                   ~~~~~~~~~~^

备注:一旦基类不依赖(即使用了具体类型,如AbsInit),就可以使用注入类名称的不合格形式。


您需要将模板参数(在本例中是T传递给基模板类。

改变这个

1
2
3
4
5
6
7
8
template<typename T>
class NotAbsTotal : public AbsInit<T>, public AbsWork<T>
{
public:
    T y;
    NotAbsTotal(int x) : AbsInit<T>(x) // You need to pass the template parameter
    {};
};