2016-07-25 2 views
4

Я следую примеру из here, однако я использую шаблоны и вызываю конструктор одного из производных классов. Следующий код работает без шаблонов, но, когда он включен, я не знаю, почему я получаю следующее сообщение об ошибке:Множественное наследование от двух производных классов с шаблонами и конструкторами

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

Вот код:

#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; 

} 
+3

'AbsInit (x)'? –

+0

@TavianBarnes ahaha спасибо! ответьте – pyCthon

+0

Это должно сработать. Но, может быть, мой обман неверен, поскольку он должен был быть исправлен в GCC 4.5, который значительно превосходил C++ 14. Каков ваш компилятор и версия? –

ответ

2

Вы должны пройти шаблонный аргумент (в этом случае T) до основания template-class.

Изменить этот

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 
    {}; 
};  
+0

Это удивительно , Предполагается, что 'AbsInit' является доступным именем, ссылаясь на' AbsInit '. Нет? –

+0

А, оказывается, я уже это делал раньше: http://stackoverflow.com/q/8887864/560648 –

+0

Хотя, предполагается, что он был исправлен в GCC 4.5, который значительно превосходит C++ 14 ... hmmm ... –

2

В приведенном ниже фрагменте кода ...

template<typename T> 
class NotAbsTotal : public AbsInit<T> 
{ 
    NotAbsTotal(int x) : AbsInit(x) {} 
}; 

... AbsInit<T> является dependent base class:

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

... и он попытался ссылаться на использование неквалифицированных injected-class-name (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.

... Однако [temp.dep]/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:

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<T> , Это имя, оставленное в покое, подчиняется unqualified name lookup и относится к шаблону класса, найденному в глобальном пространстве имен.

Чтобы избежать ошибки или обеспечить желаемое разрешение имен, добавьте список аргументов шаблона для класса имя шаблона AbsInit:

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

или использовать уточненное имя:

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

Примечание: после того, как базовый класс не зависит (т. е. используется конкретный тип, например, AbsInit<int>), вы можете использовать неквалифицированную форму имени введенного класса.

Смежные вопросы