6

为什么调用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代码将工作,但第二个 f被调用(它打印“通用”)。但我想做的是接到第一个电话。我认为 adynamic_cast会起作用,但由于某种原因它会导致问题。我在这里做错了什么?

4

4 回答 4

10

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

所以你b不能通过 type处理A

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

class B : public 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());
于 2012-12-13T23:00:30.043 回答
4

A是 的私有基础B,因此很少有地方B可以将类型对象视为A&. 如果您将继承更改为 public,则强制转换将起作用,并选择非模板版本的f. 但是dynamic_cast大材小用;每个 typeB的对象都是 type 的对象A,所以你可以用它static_cast来消除调用的歧义。

于 2012-12-13T23:04:04.357 回答
2

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

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

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

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

于 2012-12-13T23:03:13.527 回答
0

如前所述,它会因为私有继承而失败,并且因为b是作为对象传递的。dynamic_cast仅适用于指针和引用。

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

于 2012-12-13T23:04:45.073 回答