【发布时间】:2021-02-03 17:16:38
【问题描述】:
我有两个基类A 和B,以及第三个类C(实际上)从这两个类派生而来。每个类都有自己的公共shared_ptr 类型。
在另一个类中,我有两个向量,我想将 A 类型的对象添加到一个向量,将 B 类型的对象添加到另一个向量,并将 C 类型的对象添加到两者。这会产生三个add 方法,分别用于这三个类。
当我尝试进一步从C 派生时,我的问题出现了:
#include <iostream>
#include <memory>
#include <vector>
class A {
public:
using shared_ptr = std::shared_ptr<A>;
virtual ~A() {};
};
class B {
public:
using shared_ptr = std::shared_ptr<B>;
virtual ~B() {};
};
class C : virtual public A, virtual public B {
public:
using shared_ptr = std::shared_ptr<C>;
virtual ~C() {};
};
class D : virtual public C {
public:
virtual ~D() {};
};
class Test {
protected:
std::vector<A::shared_ptr> vecA;
std::vector<B::shared_ptr> vecB;
public:
void add(const A::shared_ptr& o) {
std::cerr << "in A" << std::endl;
vecA.push_back(o);
}
void add(const B::shared_ptr& o) {
std::cerr << "in B" << std::endl;
vecB.push_back(o);
}
void add(const C::shared_ptr& o) {
std::cerr << "in C" << std::endl;
vecA.push_back(o);
vecB.push_back(o);
}
};
int main()
{
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
auto c = std::make_shared<C>();
auto d = std::make_shared<D>();
Test t;
t.add(a);
t.add(b);
t.add(c);
t.add(d);
}
这不起作用 - 无法确定调用哪个版本的 add:
test.cc:62:7: error: call to member function 'add' is ambiguous
t.add(d);
~~^~~
test.cc:34:10: note: candidate function
void add(const A::shared_ptr& o) {
^
test.cc:39:10: note: candidate function
void add(const B::shared_ptr& o) {
^
test.cc:44:10: note: candidate function
void add(const C::shared_ptr& o) {
^
我确实可以选择简单地将我的C 对象分别传递给Test::add(const A::shared_ptr&) 和Test::add(const B::shared_ptr&),因为实际上B 版本的add 具有解决过载的附加参数,但我更喜欢这样调用者不必记住这样做。
这种歧义可以解决吗?我的目标环境限制我使用 C++14。
【问题讨论】:
-
请发布真实代码。
cls::add(const A::shared_ptr& o)缺少返回类型,所有别名都是私有的。 -
您能否在edit 这个问题中包含一个出现此问题的minimal reproducible example 程序?
-
我没有让它失败:/ godbolt.org/z/sK61Tr
-
在我的机器上工作。我认为错误在于未提供的代码中。
-
值得注意的是,这不是原始指针的问题 (wandbox.org/permlink/u12WIaINyE3fsIUa)。标准派生到碱基的转换序列根据继承链的长度进行排名。不幸的是,智能指针不能轻易模仿。
标签: c++ templates inheritance c++14