【问题标题】:Inheritance and templates in C++ - why are inherited members invisible?C++ 中的继承和模板 - 为什么继承的成员不可见?
【发布时间】:2010-12-06 18:23:51
【问题描述】:

当一个模板从另一个模板公开继承时,基本的公共方法不应该是可访问的吗?

template <int a>
class Test {
public:
    Test() {}
    int MyMethod1() { return a; }
};

template <int b>
class Another : public Test<b>
{
public:
    Another() {}
    void MyMethod2() {
        MyMethod1();
    }
};

int main()
{
    Another<5> a;
    a.MyMethod1();
    a.MyMethod2();
}

好吧,GCC 在这方面废话了……我一定遗漏了一些完全明显的东西(大脑融化)。帮忙?

【问题讨论】:

  • 您在第二类定义后遗漏了一个分号。
  • 您缺少一个 ;在class Another 的末尾。如果你解决了这个问题,那么它在 VS2008 中可以正常编译
  • @Naveen:VC 接受这是因为它没有实现正确的两阶段查找。
  • @OldCoder:请尝试发布仅包含您感兴趣的问题的代码。否则您会得到很多答案,指出许多(其他)问题。
  • @OldCoder:当您询问有关错误的问题时,您应该发布错误消息。

标签: c++ inheritance templates


【解决方案1】:

这是有关从属名称的规则的一部分。 Method1 不是Method2 范围内的从属名称。所以编译器不会在依赖的基类中查找它。

有两种方法可以解决这个问题:使用this 或指定基本类型。有关此very recent postC++ FAQ 的更多详细信息。另请注意,您错过了 public 关键字和分号。这是您的代码的固定版本。


template <int a>
class Test {
public:
    Test() {}
    int MyMethod1() { return a; }
};

template <int b>
class Another : public Test<b>
{
public:
    Another() {}
    void MyMethod2() {
        Test<b>::MyMethod1();
    }
};

int main()
{
    Another<5> a;
    a.MyMethod1();
    a.MyMethod2();
}

【讨论】:

  • 是的,这是正确的答案。 (请注意,TTBOMK、this-&gt;MyMethod1() 也应该可以工作。)
  • 如果您认为有必要这样做很疯狂,那么您并不孤单。尽管如此,这一个可悲的生活事实。
  • +1。另外值得一读的是 C++ 模板常见问题解答:womble.decadentplace.org.uk/c++/template-faq.htmlvery nice!
  • 这是一个不错的,litb。我不知道 Ben 的网站。
  • 也可以在class Another 中的某处声明using Test&lt;b&gt;::MyMethod1()
【解决方案2】:

您应该完全符合MyMethod1 的要求。 C++ 标准在 14.6.2/3 中明确说明了这一点:

在类模板或类模板成员的定义中,如果类模板的基类依赖于模板参数,则在定义点的非限定名称查找期间不会检查基类范围类模板或成员,或在类模板或成员的实例化期间。

所以,你应该写:

void MyMethod2() {
    Test<b>::MyMethod1();
}

【讨论】:

  • 如果您想知道“为什么类模板的基类依赖于模板参数时会出现愚蠢的限制?”,请参阅@ 987654321@
【解决方案3】:

main 需要一个返回类型。

class Another 需要一个结束分号。

class Another 需要它的成员是公开的。

此外,方法通常不被认为是不可见的;如果没有 public access 关键字,这些方法是无法访问的。

【讨论】:

  • 根据c++标准在main()中省略return语句是可以的,此时返回0。
  • IOW - 我的意思是 decl 中缺少类型,而不是 main 主体中的返回值。
【解决方案4】:

我将您的代码清理为:

template <int a>
class Test {
public:
    Test() {}
    int MyMethod1() { return a; }
};

template <int b>
class Another : public Test<b>
{
public:
    Another() {}
    void MyMethod2() {
        MyMethod1();
    }
};


int main()
{
    Another<5> a;
    a.MyMethod1();
    a.MyMethod2();
}

并用-fpermissive 编译没有问题(你可能可以解决这个问题)。

【讨论】:

  • 这仍然有一个错误(它不应该在符合标准的编译器中编译)。请参阅下面的帖子。
  • 只要禁用语言扩展关闭(默认),MSVC 就会构建它。
  • 那是因为 VC 没有正确的两阶段查找。基本上,仅在实例化模板时才查找符号。 (我认为它做得更多,但几乎没有。令人惊讶的是,在有人实例化模板之前,如果没有两阶段查找,什么样的愚蠢错误会被忽视。如果你编写了模板,那可能会很尴尬。)
【解决方案5】:

我认为您只是缺少一个 public: 在另一个定义的顶部。对于此类问题,发布您收到的错误消息通常会有所帮助。

【讨论】:

    猜你喜欢
    • 2011-03-03
    • 2011-03-03
    • 2017-04-29
    • 2012-02-13
    • 1970-01-01
    • 2011-09-29
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多