【发布时间】:2012-01-26 19:02:32
【问题描述】:
这是我本周遇到的一个难题。部分原因是我在编写 Java 一段时间后才回到 C++ 编码。给定以下代码:
class Base {
};
class A : Base {
public:
virtual void run() { cout << "This is A." << endl; }
};
class B : Base {
public:
virtual void run() { cout << "This is B." << endl; }
};
class C : A, B {
public:
void run() { cout << "This is C." << endl; }
};
int main(int argc, char* argv[])
{
shared_ptr<A> ptrToA = shared_ptr<C>(new C());
cout << "Pointer to A: " << ptrToA.get() << endl;
cout << "Dynamic Cast A ptr to C: " << dynamic_pointer_cast<C>(ptrToA) << endl;
ptrToA->run();
assert(dynamic_pointer_cast<C>(ptrToA));
cout << "Success!" << endl;
}
为什么会产生如下输出?
Pointer to A: 0x1f29c010
Dynamic Cast A ptr to C: 0
Running...
This is C.
tester-cpp: tester.cpp:89: int main(int, char **): Assertion `dynamic_pointer_cast<C>(ptrToA)' failed.
因为 "This is C" 打印出来了,很明显多态性正在工作,但是当将 shared_ptr 从 "A" 基类动态转换为 "C" 时,它会失败。这周我在这个微妙的问题上浪费了几个小时!希望任何答案都能避免未来遇到类似问题的编码人员浪费这么多时间(这个错误非常微妙,尤其是在编写了一段时间的 Java 代码之后)。
为什么? (我给你一个提示……这段代码是在 Linux 上使用 Intel C++ 编译器 12.1.0 编译的。我用另一个编译器尝试过,我的代码编译失败!)
【问题讨论】:
-
因为
C私下继承自A和B;将class C : A, B更改为class C : public A, public B或struct C : A, B。此外,使用A*时会打印出“This is C”,但我怀疑使用B*时不会打印出来;run()最初可能需要在Base中声明,并且您可能需要使用虚拟继承。 -
您使用的是
shared_ptr的什么实现?我预计shared_ptr<A> ptrToA = shared_ptr<C>(new C());会失败,因为A是C的一个不可访问的基础。 -
你应该在没有智能指针的情况下尝试它,然后我怀疑这可能适用:stackoverflow.com/questions/7210321/…
-
gcc 无法编译,并出现“错误:从 'std::shared_ptr
' 转换为非标量类型 'std::shared_ptr' 请求”,我认为应该如此。 -
具有讽刺意味的是,我们的 makefile 被设置为引入 std::tr1::shared_ptr 的 g++ 实现!用gcc编译时,我的4.5报错“‘A’ is an inaccessible base of ‘C’”,问题就很明显了。
标签: c++ polymorphism shared-ptr