C ++:函数调用使用Typename作为Base的模板类的编译时错误

时间:2016-02-24 16:35:36

标签: c++ templates inheritance

我不知道也无法找到概念名称来简单地形成我的问题(还有标题)。所以我发布了整个代码。下面是代码,有两个基类。一个使用类模板创建的派生类。 Derive类使用typename T继承两个基类。每个基类都有一个名为foo()&的唯一函数。嘘()。

我的问题是:
1)在这种情况下,是否可以在派生类中使用函数调用(在callMethods()中)?我收到错误,不知道解决它 2)如果现有设计错误,我还需要更改课程设计吗? 3)如果设计正确,设计这样的课程是一个好习惯吗?

错误消息:

error: 'boo' is not a member of 'mybase_1'
         T::boo();     
error: 'foo' is not a member of 'mybase_2'
         T::foo();      
                ^                ^

测试代码:

enum class myenum : int {one, two};

class mybase_1{
protected:
    void foo(){
        qDebug() << "foo called\n";
    }
};

class mybase_2{
protected:
    void boo(){
        qDebug() << "boo called\n";
    }
};

template <typename T>
class myderived : public T{
public:
    myderived(myenum _enm);
    void callMethods();
private:
    myenum enm;
};

template <typename T> myderived<T>::myderived(myenum _enm):enm{_enm}{
    qDebug() << "derived constructor\n";
}
template <typename T> void myderived<T>::callMethods(){
    switch(enm){
    case myenum::one:
        T::foo();
        break;
    case myenum::two:
        T::boo();
        break;
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    myderived<mybase_1> tmp1(myenum::one);
    tmp1.callMethods();
    myderived<mybase_2> tmp2(myenum::two);
    tmp2.callMethods();

    return a.exec();
}

2 个答案:

答案 0 :(得分:2)

  

1)在这种情况下,是否可以在派生类中使用函数调用?

在您的实现中,仅当派生类或基类实现这两个函数时。

  

我收到错误,不知道要解决它。

该类型在编译时是已知的,因此最简单的解决方案是专门化模板:

template<>
void myderived<mybase_1>::callMethods(){
    foo();
}
template<>
void myderived<mybase_2>::callMethods(){
    boo();
}

如果您不需要枚举,那么您可以将其与switch语句一起丢弃。

答案 1 :(得分:1)

1)只是为了纠正你的错误 - 你的开关案例是

switch(enm){
case myenum::one:
    T::foo();
    break;
case myenum::two:
    T::boo();
    break;
}

假设T同时具有foo()和boo()。在两个基类中定义这两个函数(如果它们是空的则无关紧要。)

我想你要做的是从派生类型调用base函数,这是继承已经被创建了。

enum class myenum : int {one, two};

class mybase_1{
protected:
    void foo(){
        qDebug() << "foo in mybase_1 is called \n";
    }
};

class mybase_2{
protected:
    void foo(){
        qDebug() << "foo in mybase_2 is called\n";
    }
};

template <typename T>
class myderived : public T{
public:
    myderived(myenum _enm);
    void callMethods();
private:
    myenum enm;
};

template <typename T> myderived<T>::myderived(myenum _enm):enm{_enm}{
    qDebug() << "derived constructor\n";
}
template <typename T> void myderived<T>::callMethods(){
    foo(); // the foo called depends on the parameter supplied to template, which determines from which class your derived class has been derived.
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    myderived<mybase_1> tmp1(myenum::one);
    tmp1.callMethods();
    myderived<mybase_2> tmp2(myenum::two);
    tmp2.callMethods();

    return a.exec();
}