Используйте конструктор копирования для "абстрактного" суперкласса - PullRequest
2 голосов
/ 04 ноября 2011

У меня есть «абстрактный» суперкласс, называемый 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.Я понятия не имею, что он должен делать.Компилятор в порядке с кодом, но, к сожалению, когда я тестирую соединение, вот так:

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)

Andprint был определен так:

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";
}

Я использую цикл для вызова функции static-print и помещаю представление между ().

Я попробовал это так, как это было предложено в Cat Plus Plus: виртуальный метод в RealAlgebraicNumber, реализация

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

, например, в NumericRepresentation

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

А затем использовал его следующим образом:

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 и виртуальным.

Спасибо!

Иоахим

1 Ответ

2 голосов
/ 04 ноября 2011

Если вы не определили копию 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);
}
...