为什么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
会起作用,但由于某种原因会导致问题。我在这里做错了什么?
答案 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)
A
是B
的私有基础,所以很少有地方可以将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
仅适用于指针和引用。