使用dynamic_cast和模板时,为什么会出现错误“A是B的无法访问的基础”?

时间:2012-12-13 22:58:41

标签: c++

为什么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(它会打印“Generic”)。但我要做的就是第一次打电话。我认为dynamic_cast会起作用,但由于某种原因会导致问题。我在这里做错了什么?

4 个答案:

答案 0 :(得分:8)

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

因此,您无法通过b类型处理A

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

class B : public A {};

编辑:
公共派生类与其基类之间的关系是“是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());

答案 1 :(得分:4)

AB私有基础,所​​以很少有地方可以将B类型的对象视为{{1} }}。如果将继承更改为public,则转换将起作用,并选择A&的非模板版本。但是f是过度的; dynamic_cast类型的每个对象都是B类型的对象,因此您可以使用A消除呼叫的歧义。

答案 2 :(得分:1)

关于upcasts,dynamic_cast并没有什么特别之处。在这种情况下,dynamic_cast相当于static_cast。如果基础存在,它是在编译时执行的,是明确的并且是可访问的。否则无法编译。

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

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

事实上,在绝大多数情况下,您并不需要任何演员来执行 legal upcast。至于非法上传,没有C ++演员可以帮助你(唯一可以“突破”私人继承的演员是C风格演员。)

答案 3 :(得分:0)

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

请参阅:http://www.cplusplus.com/doc/tutorial/typecasting/