Вопрос

Given:

class Base:
{
  public:
  ...
  Base operator+( const Base& other );
  Base& scale( float num );
}

class Derived : public Base:
{
  public:
  ...
  Derived( const Base& other );
  float super_math_wizardry();
}

//A user can do the following:

Base b1,b2,b3;
Derived d1,d2,d3;

b3 = b1 + b2;
d3 = d1 + d2;

b3 = b1.scale( 2.0f );
d3 = d1.scale( 3.0f ); //scale returns Base& type that is converted to Derived

float x,y;

x = (d1+d2).super_math_wizardry(); //compiler type error since d1+d2 returns Base type
y = (d1.scale(4.0f)).super_math_wizardry(); //similar compiler error

x = Derived(d1+d2).super_math_wizardry(); //works
y = Derived(d1.scale(4.0f)).super_math_wizardry(); //works

Is there a way to make the first two statements work without re-implementing every Base method in Derived (make Derived methods that call Base methods and returns Derived types) and without requiring the user to make casts/call copy constructors?

EDIT: All Derived objects are in the set of Base objects (as is needed for the class inheritance), but not all Base objects are in the set of Derived objects. They have the same data members, but a Derived object has a constant value assigned to one of those data members (the same constant value for all Derived objects).

There are many methods that are Base or Derived specific, but most of the operators and set/get accessors have the same defined behavior on Base and Derived objects. The thing I'm trying to do is get a Derived or Derived& back when I call a Base method on a Derived object (since these operations are mathematically defined to do so), while still getting a Base or a Base& when calling a Base method on a Base object.

CONTEXT: Base is a Matrix class and Derived is a Vector (column) class. The Derived( const Base& other ) constructor was made for explicitly getting a Vector from a single column (nx1) Matrix.

So I want:

x = (d1+d2).super_math_wizardry(); //works
y = (b1+b2).super_math_wizardry(); //fails (although possibly at run-time since a nx1 Matrix is a column vector)
Это было полезно?

Решение

Given your context, I think the fundamental problem you have is informing the compiler that the set of Derived objects is closed under operator+. I know it, you know it, but there's no special shortcut in the C++ language to express it. You do need to implement Derived Derived::operator+(const Derived&) const.

I'd probably make the Derived(const Base &other) constructor explicit. Presumably it throws an exception if the dimensions of other are wrong, so it's not something that users should expect to happen implicitly. They need to know it's right, so they might as well have to say that they want it to happen.

Другие советы

Well the short answer is, no.

The functions have a return type of Base. What you are asking the compiler to do is no different than doing

Derived d1;
Base* b = &d1;
b->super_math_wizardry(); // This is also wrong since we don't know that b can be
                          // a derived class

There is simply no way to do this because there is no way for the language to know the difference between the above and

Base* b1 = new Base();
b1->super_math_wizardry(); // This is just plain wrong
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top