错误的私人基类无法访问?

时间:2010-07-12 03:24:58

标签: c++ private base-class name-lookup private-inheritance

使用g ++ 4.2.1编译此代码:

struct S { };
template<typename T> struct ST { };

template<typename BaseType>
class ref_count : private BaseType { };

template<typename RefCountType>
class rep_base : public RefCountType { };

class wrap_rep : public rep_base<ref_count<S> > {
  typedef rep_base<ref_count<S> > base_type;      // line 11
};

我明白了:

bug.cpp:1: error: ‘struct S’ is inaccessible
bug.cpp:11: error: within this context

但是,如果我将wrap_rep类更改为使用ST

class wrap_rep : public rep_base<ref_count< ST<int> > > {
  typedef rep_base<ref_count< ST<int> > > base_type;
};

它编译得很好。或者,如果我将原始代码更改为:

class wrap_rep : public rep_base<ref_count<S> > {
  typedef rep_base<ref_count< ::S > > base_type;  // now using ::
};

它编译也很好。对我来说,原始代码看起来很好。这是一个g ++错误吗?如果没有,那么为什么使用模板工作呢?而且,对于另一种情况,为什么::S是必要的?

3 个答案:

答案 0 :(得分:7)

这两个代码都是无效的(只有最后一个有效),但是你的编译器(不符合)只能诊断一个。正如另一个答案所说,这使用了注入的类名。类S被认为具有表示同一类的成员名S。例如(注意第一个示例中S::S之前的“class”关键字是强制引用注入的类名而不是默认构造函数所必需的):

class S { };

class S::S object; // creates an S object
class X : S::S::S::S { }; // derives from class S

类模板也有一个注入的类名。与注入的类名一样,它继承到派生类,因此ST<int>格式不正确,因为它使用了注入的类名,但是无法访问它。如果你使用GCC减去4.5,它可能与change introduced与GCC4.5有关:

  

G ++现在实现DR 176.以前G ++不支持使用模板基类的inject-class-name作为类型名称,并且查找名称在封闭范围内找到模板的声明。现在查找名称会找到inject-class-name,它可以用作类型或模板,具体取决于名称后面是否有模板参数列表。由于此更改,以前接受的某些代码可能格式不正确,因为

     
      
  1. 无法访问inject-class-name,因为它来自私有基础,或
  2.   
  3. inject-name-name不能用作模板模板参数的参数。
  4.         

    在这两种情况中,可以通过添加嵌套名称说明符来明确命名模板来修复代码。第一个可以使用-fno-access-control解决;第二个只是被拒绝了。


为了让注入的类名更有趣 - 请注意注入的类名不等于首先想到的typedef。注入的类名是类名,但不归类为typedef-name,这意味着它可以被函数,对象或枚举器名称隐藏:

// valid, the data-member hides the injected class name
struct S { int S; };

要引用注入的类名,您可以说class S::S(同样,在基类列表中,忽略非类型名称,因此您不需要特别的注意事项),但是很简单查找到S::S将引用数据成员。

答案 1 :(得分:3)

你的结构Swrap_rep的基类,这意味着它被注入wrap_rep,好像有一个匿名的typedef。

在typedef中使用::之前的运算符S将告诉编译器不要使用您继承的S,而是使用全局命名空间中的S

请参阅this link

答案 2 :(得分:0)

原始代码在“Sun WorkShop 6 update 2 Compilers C ++”中编译得很好。这是我在办公室里唯一可以访问的。可以试试你拥有的任何其他编译器。