【问题标题】:template inheritance c++模板继承 C++
【发布时间】:2011-04-17 12:03:52
【问题描述】:

我是 C++ 的新程序员。我是第一次使用模板。

我有一个抽象类和另一个扩展它的类。但是抽象类的所有受保护成员都不被其他类识别:

class0.h:

template<class T>
class class0 {

protected:
    char p;
public:
    char getChar();
};

**class1.h**
template<class T>
class class1:public class0<T> {
public:
    void printChar();
};
template<class T>
void class1<T>::printChar(){
    cout<< p<<endl;//p was not declared in this scope
}

谢谢。祝你度过愉快的一周 =)

【问题讨论】:

  • 您的基类要么需要公共虚拟析构函数,要么需要受保护/私有的非虚拟析构函数。
  • 顺便说一句,这里面哪个类是抽象的?

标签: c++ templates inheritance


【解决方案1】:

发生这种情况的原因与模板的查找规则有关。

p 不是依赖表达式,因为它只是一个标识符,而不是依赖于模板参数的东西。这意味着不会搜索依赖于模板参数的基类来解析名称p。要解决此问题,您需要使用依赖于模板参数的东西。使用this-&gt; 可以做到这一点。

例如

cout << this->p << endl;

【讨论】:

  • @GMan:我不知道; litb 现在已经发布了答案。 :-)
  • 不,我只是在吹毛求疵 :)
【解决方案2】:

要在依赖基类中查找名称,需要满足两个条件

  • 必须查找不是不合格的
  • 名称依赖是必要的

C++03 中所述的这些规则与 rules stated by unrevised C++98 不同,其中满足第二个项目符号(使名称依赖)对于查找在依赖基类中声明的名称​​足够

在实例化时查找从属名称,并且非限定查找以外的查找不会忽略从属基类。需要同时满足这两个条件才能找到在依赖基类中声明的名称,单靠这两个条件都不够。为了满足这两个条件,您可以使用各种构造

this->p
class1::p

p 两个名称是相互依赖的,第一个版本使用类成员访问查找,第二个版本使用限定名称查找

【讨论】:

    【解决方案3】:

    我没有在 VC9 中得到那个编译器错误。但是,代码有几个问题:首先,它不需要像当前编写的那样是模板类……但也许您只是为这个问题简化了它?其次,基类应该有一个虚析构函数。

    #include <iostream>
    
    using namespace std;
    
    class class0 {
    public:
       virtual ~class0(){}
    
    protected:
        char p;
    public:
        char getChar();
    };
    
    class class1 : public class0 {
    public:
        void printChar();
    };
    
    void class1::printChar(){
        cout << p << endl;//p was not declared in this scope
    }
    
    int main() {
       class1 c;
       c.printChar();
       return 1;
    }
    

    由于您正在学习模板,我建议您在学习时不要混合概念(继承和模板)。从这样一个简单的例子开始......

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    template <typename T>
    T add(const T& a, const T& b) {
       return a + b;
    }
    
    int main() {
       int x = 5;
       int y = 5;
    
       int z = add(x, y);
       cout << z << endl;
    
       string s1("Hello, ");
       string s2("World!");
    
       string s3 = add(s1, s2);
       cout << s3 << endl;
    
       return 1;
    }
    

    上面代码中的重要概念是我们编写了 ONE 函数,它知道如何添加整数和字符串(以及许多其他类型)。

    【讨论】:

    • 为什么基类要有虚析构函数?模板通常用于实现参数多态,而虚拟删除仅对动态多态有用(并且仅当删除以多态方式完成时)。
    • 已知 Visual Studio 2008 编译器在这种情况下无法正确实现模板查找规则。这就是您看不到错误的原因。
    • @Ben Voigt,好点,但 OP 只是从模板开始,我猜他们可能还没有涵盖。但看起来他们确实涵盖了继承,除非他专门用于编译时多态,否则将基本析构函数设为虚拟是最安全的。
    • @Charles Bailey,感谢您提供的信息。我会仔细阅读。
    • 作为一般准则,如果基类没有任何其他虚函数,则不需要虚析构函数。这里就是这种情况。多态删除非多态的类是非常罕见的。
    【解决方案4】:

    很抱歉再次提出这样一个老问题,但我只是想添加这个东西,如果你的成员函数中有很多很多“p”,我认为它很有价值。

    class class1:public class0<T> {
    public:
        using class0<T>::p; // add this line and in all member functions 
                            // will assume that "p" is the p from class0<T>
                            // very useful if you have hundreds of "p":s
                            // and don't want to replace every single one with "this->p"
        void printChar();
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多