简体   繁体   English

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

[英]Why am I getting the error “A is an inaccessible base of B” when using dynamic_cast and templates?

Why is the call to f not resolving to the first function overload? 为什么对f的调用没有解析为第一个函数重载? I get the error: 我收到错误:

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));

}

Note that if I take out the dynamic_cast the code will work yet the second f is called (it prints "Generic"). 请注意,如果我取出dynamic_cast ,代码将工作,然后调用第二个 f (它打印“Generic”)。 But what I'm trying to do is to get the first call. 但我要做的就是第一次打电话。 I figured a dynamic_cast would work, but for some reason it causes problems. 我认为dynamic_cast会起作用,但由于某种原因它会导致问题。 What am I doing wrong here? 我在这做错了什么?

The default class inheritance is private ( class B : A {}; defaults to class B : private A {}; ). 默认的类继承是private( class B : A {};默认为class B : private A {}; )。

So you can't handle b through type A . 所以你不能通过A型处理b

EDIT: Like Rob said :), the way to fix it is by using public inheritance: 编辑:像Rob说:),修复它的方法是使用公共继承:

class B : public A {};

EDIT: 编辑:
The relationship between a publicly derived class and its base class is "is a", meaning that it is a specialization of a more generic type, and as such, it implements the behavior of that generic class and possibly more. 公共派生类与其基类之间的关系是“是一个”,这意味着它是更通用类型的特化,因此,它实现了该泛型类的行为,甚至可能更多。

The relationship between a privately derived class and its base class is "implemented in terms of". 私有派生类与其基类之间的关系是“根据”实现的。 It prevents objects from being considered extensions of the base class. 它可以防止对象被视为基类的扩展。 A good example of its use is boost::noncopyable that prevents objects of a privately derived class from being copied. 它使用的一个很好的例子是boost::noncopyable ,它可以防止私有派生类的对象被复制。 http://www.boost.org/doc/libs/1_52_0/libs/utility/utility.htm#Class_noncopyable http://www.boost.org/doc/libs/1_52_0/libs/utility/utility.htm#Class_noncopyable

In the hypothetical case that the requirements include private inheritance and at some point a function is created that wants to reference the object as its base, a public method returning a casted to base class pointer this will do it much like a traditional get() accesses a private data member maintaining the original purpose. 在假设的情况下,需求包括私有继承,并且在某些时候创建了一个想要引用该对象作为其基础的函数,一个返回一个转换为基类指针的公共方法, this将像传统的get()访问一样保持原始目的的私人数据成员。

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

And then accessed like this: 然后像这样访问:

f(b.getBase());

A is a private base of B , so there are very few places where an object of type B can be treated as an A& . AB私人基础,因此很少有地方可以将B类对象视为A& If you change the inheritance to public the cast will work, and select the non-template version of f . 如果将继承更改为public,则转换将起作用,并选择f的非模板版本。 But dynamic_cast is overkill; 但是dynamic_cast过分了; every object of type B is an object of type A , so you can use static_cast to disambiguate the call. 该类型的每个对象B是类型的对象A ,所以你可以使用static_cast来澄清对通话。

There's nothing special about dynamic_cast when it comes to upcasts. 关于upcasts, dynamic_cast没有什么特别之处。 dynamic_cast is equivalent to static_cast in such cases. 在这种情况下, dynamic_cast相当于static_cast It is performed at compile-time if the base exists, is unambiguous and is accessible. 如果基础存在,它是在编译时执行的,是明确的并且是可访问的。 It fails to compile otherwise. 否则无法编译。

This is exactly what happens in your case. 这正是你的情况。 The base is inaccessible (as the compiler told you already) so the cast fails to compile. 基础是不可访问的(正如编译器已经告诉你的那样),因此转换无法编译。

Without the cast the first function is excluded from the overload resolution candidate list (since the base is inaccessible), and the second one wins. 如果没有强制转换,第一个函数将从重载决策候选列表中排除(因为基数是不可访问的),第二个函数获胜。

In fact, you don't really need any cast to perform legal upcasts in overwhelming majority of cases. 事实上,在绝大多数情况下,你真的不需要任何演员来执行合法的上调。 As for illegal upcasts, no C++ cast will help you with that (the only cast that can "break through" private inheritance is C-style cast.) 至于非法上传,没有C ++演员可以帮助你(唯一可以“突破”私人继承的演员是C风格演员。)

It will fail because of the private inheritance, as mentioned, and because b is passed as an object. 如上所述,它将因私有继承而失败,并且因为b作为对象传递。 dynamic_cast will only work for pointers and references. dynamic_cast仅适用于指针和引用。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM