【问题标题】:Use copy constructor for "abstract" super class对“抽象”超类使用复制构造函数
【发布时间】:2011-11-04 16:50:23
【问题描述】:

我有一个名为 RealAlgebraicNumber 的“抽象”超类和两个名为 IntervalRepresentation 和 NumericRepresentation 的继承类。 IntervalRepresentation 和 NumericRepresentation 都有一个复制构造函数,它们工作正常。

我是这样使用 shared_ptr 的:

typedef std::tr1::shared_ptr<RealAlgebraicNumber> RealAlgebraicNumberPtr;

在程序的另一部分,我想使用抽象超类 RealAlgeraicNumber 的复制构造函数:

RealAlgebraicPoint RealAlgebraicPoint::conjoin (const RealAlgebraicNumber& N)
{
    vector<RealAlgebraicNumberPtr> v (mNumbers.begin(), mNumbers.end());
    v.push_back(RealAlgebraicNumberPtr(new RealAlgebraicNumber(N)));
    return RealAlgebraicPoint(v);
}

我根本没有为 RealAlgebraicNumber 定义复制构造函数。我不知道它应该做什么。编译器对代码很好,但不幸的是,当我像这样测试 conjoin 时:

vector<RealAlgebraicNumberPtr> v;
v.push_back(RealAlgebraicNumberPtr(new NumericRepresentation(2)));
RealAlgebraicPoint PPP (v);
PPP.print();
PPP = PPP.conjoin (NumericRepresentation(3));
PPP.print();

输出是:

( 2 )( 2 null )

打印是这样定义的:

void RealAlgebraicNumberFactory::print (const RealAlgebraicNumberPtr& A)
{
    IntervalRepresentationPtr irA = std::tr1::dynamic_pointer_cast<IntervalRepresentation> (A);
    NumericRepresentationPtr nrA = std::tr1::dynamic_pointer_cast<NumericRepresentation> (A);
    if (irA != 0)
        cout << irA->Interval();
    else if (nrA != 0)
        cout << static_cast<numeric>(*nrA);
    else
        cout << "null";
}

我使用循环调用静态打印函数并将表示放在 ( ) 之间。

我按照 Cat Plus Plus 提出的方式进行了尝试:RealAlgebraicNumber 中的虚拟方法,

virtual std::tr1::shared_ptr<RealAlgebraicNumber> clone();

在例如实现数值表示

RealAlgebraicNumberPtr NumericRepresentation::clone()
{
    return RealAlgebraicNumberPtr(new NumericRepresentation(*this));
}

然后在 conjoin 中这样使用:

RealAlgebraicPoint RealAlgebraicPoint::conjoin (const RealAlgebraicNumber& N)
{
    vector<RealAlgebraicNumberPtr> v (mNumbers.begin(), mNumbers.end());
    v.push_back(RealAlgebraicNumberPtr(N.clone()));
    return RealAlgebraicPoint(v);
}

现在编译器抱怨:

RealAlgebraicPoint.cpp: In member function 'GiNaC::RealAlgebraicPoint  GiNaC::RealAlgebraicPoint::conjoin(const GiNaC::RealAlgebraicNumber&)':
RealAlgebraicPoint.cpp:66:48: error: passing 'const GiNaC::RealAlgebraicNumber' as 'this' argument of 'virtual std::tr1::shared_ptr<GiNaC::RealAlgebraicNumber> GiNaC::RealAlgebraicNumber::clone()' discards qualifiers

我不明白!怎么了?

编辑:没关系!它与 const 和 virtual 有关。

谢谢!

约阿希姆

【问题讨论】:

  • 什么是RealAlgebraicPoint
  • 我们可以简化这个问题吗?你有class Base;class D1 : public Base; class D2 : public Base;,你问如何为Base 写一个拷贝构造函数?
  • 你真的会在同一个程序中同时拥有两种实数表示吗?如果没有,您可以创建一个模板化的RealAlgebraicNumberFactory&lt;T&gt; 和一组模板化操作,例如template&lt;typename T&gt; T conjoin(const T&amp;),由您选择的表示进行参数化。
  • @KerrekSB 我认为最好使用 OP 的现有示例来回答。对他来说,用他可以理解的术语来理解概念会更容易,而不是没有意义的抽象字母。
  • @EmileCormier:也许吧,但我有点沮丧的是,带有areallylongidentifier 的类仅在最后几个字母上有所不同,并且从未定义过。在精神上通读和推理是很乏味的。无论如何,看起来像 CatPlusPlus 管理 :-)

标签: c++ oop tr1


【解决方案1】:

如果你没有定义一个复制ctor,编译器会生成一个默认的,做成员复制。您可能想要的是多态克隆,以保留类型并调用适当的复制 ctor。为此,添加一个新的虚拟成员,例如virtual RealAlgebraicNumber* clone();,并在每个子类中重写它以执行 return new T(*this); — 那么您的 conjoin 将如下所示:

RealAlgebraicPoint RealAlgebraicPoint::conjoin (const RealAlgebraicNumber& N)
{
    vector<RealAlgebraicNumberPtr> v(mNumbers.begin(), mNumbers.end());
    v.push_back(RealAlgebraicNumberPtr(N.clone()));
    return RealAlgebraicPoint(v);
}

【讨论】:

  • 返回一个动态对象似乎是错误的。也许最好再次返回一个共享指针。
  • @KerrekSB:它可以返回一个共享指针,无论如何。关键是,它必须在正确的类型上调用,即它必须是虚拟的。
猜你喜欢
  • 2010-12-02
  • 2011-07-21
  • 2018-09-16
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 2010-11-26
相关资源
最近更新 更多