【问题标题】:Polymorphism, why can't I do this?多态,为什么我不能这样做?
【发布时间】:2012-04-22 22:37:51
【问题描述】:
class BaseA
{
}

class B : public BaseA
{
}

template <class T>
class C : public vector<T>
{
}

void someFunction (void)
{
    C<B> myClass;

    // I can't seem to do this...is it not possible?
    vector<BaseA> converted = ((vector<BaseA>) myClass);
}

请参阅代码中的注释了解我想要做什么。

【问题讨论】:

标签: c++ oop templates polymorphism


【解决方案1】:

即使 B 是 A,B 的向量也不是 A 的向量(我假设 A 和 BaseA 之间存在混淆)

试试

vector<A> converted(myClass.begin(), myClass.end());

这可能就是你想要表达的。

(顺便说一句,继承自向量 is bad idea in general,它不是为此而设计的。)

【讨论】:

  • 这是很重要的一点。从任何 STL 容器继承都不是一个好主意,因为它们没有虚拟析构函数。如果必须,请使用容器作为成员。
  • 您提出的解决方案在功能上很有用,但它不会改变所需的行为,因为现在转换的是 myClass 的浅拷贝,而不是对同一向量的引用?
  • @Alain Here converted 保存myClass 中对象的深层副本。在原始版本中,如果它有效,converted 将保存myClass 中对象的深层副本。贴出的代码中没有引用。
  • 不允许期望的行为(原因很明显)。如果您在解析数组时忽略只转换迭代器,这是您将得到的最接近的结果。
  • 我明白了...我认为目的是让两个变量指向内存中的同一个对象。可能我做 C# 也太久了。
【解决方案2】:

C&lt;B&gt;vector&lt;A&gt; 是完全不相关的类型,您必须明确定义这样的转换(例如 template &lt;typename TargetValueType&gt; explicit operator vector&lt;TargetValueType&gt; () { ... })。

如果这种转换是一项不常见的任务,这对你的类的性质来说并不是很自然,那么最好使用范围构造函数(参见 AProgrammer 的回答)。

另外:如果vectorstd::vector,则从它派生不是一个好主意。它没有被定义为基类,通常你应该更喜欢包含而不是派生(因为它对你的客户端施加了更松散的耦合)。

【讨论】:

    【解决方案3】:

    没办法,没办法。想象一下,如果你有另一个类X,它派生自BaseA。如果您可以获得converted 对象,您可以在其中插入X 的实例,即使原始对象不允许这样做。你会破坏变量的语义。

    顺便说一句,您可以在 Java 中做到这一点,他们没有真正意义上的泛型,但在 C# 或 C++ 等强类型泛型语言中,您将无法做到这一点(使用C# 中的异常,但无论如何你都不应该在这种情况下使用它)。

    【讨论】:

    • 协方差在这里并不重要。转换后的对象是一个副本,包含(可能是切片的)原始副本。将Xs 插入其中可以正常工作(除了Xs 将被切片),因为它不会在原始对象中插入任何内容。
    猜你喜欢
    • 2011-11-20
    • 2023-03-27
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    相关资源
    最近更新 更多