【问题标题】:Why am I getting the error "A is an inaccessible base of B" when using dynamic_cast and templates?为什么在使用 dynamic_cast 和模板时出现错误“A 是 B 的不可访问的基础”?
【发布时间】:2012-12-13 22:58:41
【问题描述】:

为什么对f 的调用没有解析到第一个函数重载?我得到错误:

source.cpp: In function 'int main()':
source.cpp:12:31: error: 'A' is an inaccessible base of 'B'

class A {}; class B : A {};

void f(const A &)  { std::cout << "const A &"; }
template <typename T> void f(T) { std::cout << "Generic";  }

int main() {

   B b;

   f(dynamic_cast<const A &>(b));

}

请注意,如果我取出 dynamic_cast 代码将工作,但 second f 被调用(它打印“通用”)。但我想做的是接到第一个电话。我认为dynamic_cast 会起作用,但由于某种原因它会导致问题。我在这里做错了什么?

【问题讨论】:

    标签: c++


    【解决方案1】:

    在向上转换方面,dynamic_cast 没有什么特别之处。在这种情况下,dynamic_cast 等效于 static_cast。如果基础存在、明确且可访问,则在编译时执行。否则无法编译。

    这正是您的情况。基础是不可访问的(正如编译器已经告诉你的那样),所以转换无法编译。

    如果没有强制转换,第一个函数将从重载解决候选列表中排除(因为基数不可访问),第二个函数获胜。

    事实上,在绝大多数情况下,您真的不需要任何强制转换来执行合法向上转换。至于非法向上转换,没有 C++ 转换可以帮助您(唯一可以“突破”私有继承的转换是 C 样式转换。)

    【讨论】:

      【解决方案2】:

      默认的类继承是私有的(class B : A {}; 默认为class B : private A {};)。

      所以你不能通过输入A来处理b

      编辑: 就像 Rob 说的 :),修复它的方法是使用公共继承:

      class B : public A {};
      

      编辑:
      publicly 派生类与其基类之间的关系是“is a”,这意味着它是更通用类型的特化,因此,它实现了该通用类的行为,并且可能更多。

      私有派生类与其基类之间的关系是“根据”实现的。它防止对象被视为基类的扩展。一个很好的使用例子是boost::noncopyable,它可以防止私有派生类的对象被复制。 http://www.boost.org/doc/libs/1_52_0/libs/utility/utility.htm#Class_noncopyable

      在假设的情况下,要求包括私有继承,并且在某些时候创建了一个想要引用该对象作为其基类的函数,一个返回转换为基类指针 this 的公共方法将非常像传统的get() 访问维护原始目的的私有数据成员。

      public:
          A *getBase() { return static_cast<A *>(this); }
      

      然后像这样访问:

      f(b.getBase());
      

      【讨论】:

      • 解决办法是class B : public A {};
      • 严格来说,说公共继承是一种“修复它的方法”是相当误导的。究竟要修复what?公共继承只不过是让编译器停止抱怨的一种方式。在 OP 的代码中是否有意义取决于 OP 的意图。这实际上可能根本没有意义。
      • @AndreyT “但我想做的是接到第一个电话。” OP 忘记或不知道输入public,这似乎很清楚。
      • @JohnKugelman - 但这是一个有效的观点。如果私有继承是经过深思熟虑的设计决定,并且调用f 的第一个版本是合适的,那么解决方案必须是改变继承以外的其他方法。诚然,这是很多假设,但这里可能并非如此。
      • @John Kugelman:代码和“获得第一个电话”的目标都过于抽象,无法以任何特定方式解释。争论“修复”的正确方法就像争论 2 + 2 = 5 出了什么问题:有些人认为它应该是 2 + 2 = 4,另一些人认为它应该是 2 + 3 = 5
      【解决方案3】:

      AB私有基,因此很少有地方可以将B 类型的对象视为A&amp;。如果您将继承更改为公共,则转换将起作用,并选择f 的非模板版本。但是dynamic_cast 太过分了;每个B 类型的对象都是A 类型的对象,因此您可以使用static_cast 来消除调用的歧义。

      【讨论】:

      • 那么在什么情况下我会使用dynamic_cast in (with classes)??
      • 反之,从A&amp;B&amp;;这将是一个检查转换,如果引用的对象不是B,你会得到一个异常。但是,要使其工作,A 必须至少具有一个虚函数。
      【解决方案4】:

      如前所述,由于私有继承以及 b 作为对象传递,它将失败。 dynamic_cast 仅适用于指针和引用。

      见:http://www.cplusplus.com/doc/tutorial/typecasting/

      【讨论】:

      • b 是一个左值,因此可以将dynamic_cast 设置为引用类型。
      猜你喜欢
      • 2017-01-12
      • 1970-01-01
      • 2012-03-28
      • 2018-11-22
      • 2019-10-27
      • 2018-11-29
      • 2014-03-29
      • 1970-01-01
      • 2014-01-15
      相关资源
      最近更新 更多