所以,问题可能有点令人困惑,但让我解释一下。
我有一个包含3个其他类和向量的类。 3个类中的2个继承自第三个类,向量用shared_ptr
填充class top_class
{
class Base
{};
class Derived1 : public Base
{};
class Derived2 : public Base
{};
std::vector<std::shared_ptr<Base>> my_vector;
};
我想创建一个下标运算符重载,它返回对Derived1或Derived2的引用,具体取决于我被要求的元素的类型。
我一直在尝试使用auto,但我对c ++ 11很新,而且我还没有完全使用它。
请记住,我被要求以这样的方式交付它,用户应该像这样调用下标运算符:
top_class tc;
Derived1 d1 = tc[ 0 ];
Derived2 d2 = tc[ 1 ];
因此使用模板化函数不是解决方案。我目前的尝试是:
auto operator[](int index) -> decltype(*my_vector[index])
{
return *my_vector[index];
}
但是当然这不起作用,因为我传递给decltype的类型是Base。
答案 0 :(得分:1)
您无法根据某些运行时状态返回变量类型。您可以做的是要求用户提供他想要的类型并使用std::dynamic_pointer_cast
:
template <class Derived>
std::shared_ptr<Derived> get(size_t idx) const
{
return std::dynamic_pointer_cast<Derived>(my_vector[idx]);
}
如果你想要抛出它,你可以检查结果是否为null并且适当地抛出:
template <class Derived>
std::shared_ptr<Derived> get(size_t idx) const
{
auto res = std::dynamic_pointer_cast<Derived>(my_vector[idx]);
if (!res) throw ...;
return res;
}
此时,我们也可以使用vector::at()
来投掷。
答案 1 :(得分:1)
给定成员变量
std::vector<std::shared_ptr<Base>> my_vector;
如果不执行动态转换,就无法从中获取派生类型的对象。
一旦引入动态强制转换,您将需要考虑动态强制转换的失败。此时,您必须在设计/实施中考虑以下因素。
当动态转换失败时,您是要抛出异常,还是要返回等同于nullptr
的内容?
您想如何调用该功能?派生类型必须作为模板参数传递。如果您选择使用operator[]
,则需要使用
auto ret = obj.operator[]<DerivedType>(index);
这种语法对我来说非常难看。也许像std::vector::at
这样的东西会更合适。
auto ret = obj.at<DerivedType>(index);
在任何一种情况下,函数的返回类型将取决于您想要如何处理失败。
如果您选择抛出异常,则需要以下内容:
template <typename DerivedType>
DerivedType& at(size_t index)
{
std::shared_ptr<Base> ptr = my_vector.at(index);
dynamic_cast* derived_ptr = dynamic_cast<DerivedType>(ptr.get());
if ( derived_ptr == nullptr )
{
throw std::bad_cast();
}
return *derived_ptr;
}
如果您选择在动态广告投放失败时返回nullptr
,则您需要以下内容:
template <typename DerivedType>
DerivedType* at(size_t index)
{
std::shared_ptr<Base> ptr = my_vector.at(index);
return dynamic_cast<DerivedType>(ptr.get());
}
请注意,如果std::vector::at
超出范围,index
会抛出异常。
答案 2 :(得分:0)
由于C ++中的返回类型是指定的编译时,因此有些不寻常的语法
top_class tc;
Derived1 d1 = tc[ 0 ];
Derived2 d2 = tc[ 1 ];
很难实现(更简单就像
Derived1 d1 = tc.get<Derived1>(0);
Derived2 d2 = tc.get<Derived2>(1);
当top_class::get<>
知道要返回的内容时。使用原始语法,top_class::operator[]
必须返回可转换为Derived1
或Derived2
的内容。据我所知,唯一的可能性是Base
,如果Derived1
和Derived2
都允许Base
进行构建:
struct top_class
{
struct Base { /* ... */ };
struct Derived1 : Base
{
Derived1(Base const&);
// ...
};
struct Derived2 : Base
{
Derived2(Base const&);
// ...
};
Base const&operator[](std::size_t i) const
{
return *(data.at(i));
}
private:
std::vector<std::shared_ptr<Base>> data;
};