Ваш вопрос сбивает с толку, и я чувствую себя здесь поспешно, но я скажу это.
Обычно операторы объявляются вне класса как функции, не являющиеся членами, и используют функции-члены для достижения своей цели. Это связано с тем, что оба аргумента оператора могут в равной степени участвовать в разрешении перегрузки.
В этом случае похоже, что вы пытаетесь создать какое-то дерево разбора на основе операторов C ++. В этом случае код, подобный этому, может быть тем, что вы ищете:
const B operator +(const B &a, const B &b)
{
return B(a, b);
}
Обратите внимание, что это будет работать, даже если что-то, полученное из B, является либо операндом. И если я прав насчет того, что вы делаете, у вас, скорее всего, будет специальный тип узла для двух вещей, добавленных к каждому другому, и оператор + может вернуть это.
Теперь, когда я вижу вашу уточненную версию, вот другой ответ.
Во-первых, я подвергаю сомнению ваше использование оператора + таким образом. Перегрузка операторов часто приводит к неожиданностям для людей, использующих ваш класс, и если ваше использование оператора + не будет вести себя так, как люди ожидают, что оператор + будет вести себя в целом, это вызовет больше проблем, которые он решает.
Но ваш реальный вопрос, кажется, вращается вокруг создания копий объектов неизвестного типа без большого количества повторяющегося кода. Когда я вижу повторяющийся код, я склонен думать о шаблонах. Вот пример кода, который, вероятно, немного сложнее, чем вам нужно, который использует шаблоны, и я думаю, что решит вашу проблему.
#include <memory>
#include <iostream>
template <class BaseType, class DerivedType>
class Cloneable {
public:
virtual ~Cloneable() {}
::std::auto_ptr<DerivedType> clone() const {
return ::std::auto_ptr<DerivedType>(static_cast<DerivedType *>(i_clone()));
}
protected:
virtual BaseType *i_clone() const {
return new DerivedType(dynamic_cast<const DerivedType &>(*this));
}
};
class A : public Cloneable<A, A> {
public:
A() {}
A(const A &b) {
const void * const voidb = &b;
const void * const voidme = this;
::std::cerr << "Creating a copy of the A at " << voidb << " and this new copy will reside at " << voidme << "\n";
};
virtual ~A() {
const void * const voidme = this;
::std::cerr << "Destroying the A at " << voidme << "\n";
}
};
template <class Derived>
class B : public A, public Cloneable<A, Derived> {
public:
B() {}
B(const B &b) {
const void * const voidb = &b;
const void * const voidme = this;
::std::cerr << "Creating a copy of the B at " << voidb << " and this new copy will reside at " << voidme << "\n";
};
virtual ~B() {
const void * const voidme = this;
::std::cerr << "Destroying the B at " << voidme << "\n";
}
// Make sure clone can be mentioned in derived classes with no ambiguity
using Cloneable<A, Derived>::clone;
protected:
// Force dominance rules to choose the correct i_clone virtual function.
virtual A *i_clone() const {
return Cloneable<A, Derived>::i_clone();
}
};
class C : public B<C> {
public:
C() {}
C(const C &b) {
const void * const voidb = &b;
const void * const voidme = this;
::std::cerr << "Creating a copy of the C at " << voidb << " and this new copy will reside at " << voidme << "\n";
};
virtual ~C() {
const void * const voidme = this;
::std::cerr << "Destroying the C at " << voidme << "\n";
}
};
class D : public B<D> {
public:
D() {}
D(const D &b) {
const void * const voidb = &b;
const void * const voidme = this;
::std::cerr << "Creating a copy of the D at " << voidb << " and this new copy will reside at " << voidme << "\n";
};
virtual ~D() {
const void * const voidme = this;
::std::cerr << "Destroying the D at " << voidme << "\n";
}
};
int main(int argc, const char *argv[])
{
C c;
D d;
::std::auto_ptr<A> cptr(c.clone());
::std::auto_ptr<A> dptr(d.clone());
cptr = dptr->clone();
return 0;
}
Я создал методы i_clone и clone, чтобы каждый класс получал версию clone, которая возвращала указатель на собственный тип класса. Мне также нужно иметь объявление using
в шаблонном классе B, чтобы убедиться, что нет никакой неоднозначности, в которой клон будет вызываться в производных классах.
Обратите внимание, что классы C и D не содержат повторяющегося кода, относящегося к созданию своих клонов.
В то время как a еще не знал об этом, это, кажется, еще одно изобретение Curiious Recurring Template идиома в применении к полиморфной конструкции копирования .