2010-01-01 1 views
3

Возможно ли наследовать идентично именованный оператор, который отличается только по типу возврата, от двух разных абстрактных классов. Если да, то они:Сложное наследование C++ с идентично указанным оператором

  • , что синтаксис для реализации операторов

  • , что синтаксис для использования/разрешающих операторов

  • , что накладные расходы в общем случае такой же, как для любая другая виртуальная функция?

, если вы можете предоставить мне ссылку или пример кода, который был бы полезен

благодаря

 
12struct abstract_matrix { 
13 virtual double& operator()(int i, int j); 
14}; 
15 
16 struct abstract_block_matrix { 
17  virtual double* operator()(int i, int j); 
18 }; 
19 
20struct block_matrix : abstract_matrix, abstract_block_matrix { 
21 
22}; 

блочная матрица должна обеспечить реализацию для обоих операторов, так что это либо матрица или матрица блоков, в зависимости от контекста. Я не знаю, как обеспечить реализацию, специфичную для класса block_matrix. прямо сейчас, это делается путем передачи объекта wrapped type в качестве последнего аргумента, но это не кажется очень чистым. Я хотел бы сохранить чистую матричную нотацию.

+2

Что вы подразумеваете под «виртуальными классами»? Вы имеете в виду виртуальное наследование? Образец кода того, что вы имеете в виду (даже если он не компилируется), будет полезен. –

ответ

1

Обратный тип функции не является частью его подписи, поэтому вы не можете иметь два оператора + (i, j) в block_matrix - это был бы двусмысленный вызов. Таким образом, множественное наследование здесь похоже на красную селедку. Ты просто не можешь этого сделать.

Что вы действительно пытаетесь сделать и почему?

В любом случае, для вашего другого вопроса: виртуальные операторы в точности похожи на виртуальные функции с точки зрения производительности и способа их работы. Есть лишь незначительные смысловые различия в том, как вы их используете, но под капотом они просто функционируют, как и любые другие.

+0

Я так не думаю. В одном случае вы переопределяете abstract_matrix :: operator, в другом случае вы переопределяете abstract_block_matrix :: operator.so в принципе, я думаю, что есть способ сделать это. У меня есть два метода обхода, но есть уродливые. – Anycorn

+0

Нет, я сказал, что это правильно. Нет способа иметь класс с двумя идентичными функциями, отличающимися только возвращаемым типом. «Обходной путь» заключается в том, чтобы они отличались больше, чем возвращаемый тип. –

+0

проверьте это. Класс A имеет функцию f, A :: f. Класс B также имеет функцию f, B :: f. Теперь C наследует A и B. Итак, теперь C имеет доступ к A :: f и B :: f. Синтаксис для простого или простого преобразования A или B. Таким образом, у вас есть доступ к обеим f, в зависимости от того, является ли C либо A, либо B, но не оба через один и тот же объект. Если оба родителя абстрактны, то C может быть получен через промежуточный частично абстрактный класс. – Anycorn

1

Вы не можете перегружать возвращаемый тип. Когда вызывается функция или оператор, компилятор должен знать, какой из них вызывать. Он не будет делать вывод о том, что в соответствии с назначением функции (оператора).

Похоже, что вы хотите реализовать математическую математику. Возможно, если вы загрузите DirectX SDK или OpenGL и посмотрите, как они это делают, вы можете получить некоторые идеи о том, как это сделать правильно.

+0

Я знаю, что типы возврата не являются перегружаемыми. Однако это не похоже на случай * наследования *, во всяком случае компилятор не жалуется. мои требования к матрице разные, ublas не совсем подходит либо – Anycorn

0

У меня есть работа, но это неудобно. Я действительно люблю шаблоны.

template<class T> 
class Base1 
{ 
}; 

template<class T> 
class Base2 
{ 
}; 

class Derived; 
template<> 
class Base1<Derived> 
{ 
public: 
    double foo(){return 0.1;} 
}; 

template<> 
class Base2<Derived> 
{ 
public: 
    int foo(){return 1;} 
}; 

class Derived 
    : public Base1<Derived> 
    , public Base2<Derived> 
{ 
public: 
    using Base1<Derived>::foo; 
}; 

int main() 
{ 
    double sum = 0; 
    Derived d; 
    sum += d.foo(); //+ .1 
    Base1<Derived> * pI = &d; 
    sum += pI->foo(); //+ .1 

    Base2<Derived> * pF = &d; 
    sum += pF->foo(); //+ 1 

    return (sum*10); 
} 

Я не мог заставить его работать без шаблонов, хотя кажется, что он должен быть в состоянии. Я не уверен, что вы можете уйти, просто используя шаблонные функции-члены так же, но моя кишка говорит «нет».

Что касается организации кода, я бы затем определил материал Base # сразу после определения или объявления Derived, так как это действительно то, для чего это необходимо. Имейте в виду, что вы можете использовать typename Base1<Derived> something, чтобы сделать вещи красивее.

Редактировать: О, право!Это не позволяет сделать «с помощью» трюк или имеют различные типы возвращения, но в противном случае проще:

class Derived 
    : public Base1 
    , public Base2 
{ 
    double Base1::foo(){...} 
    double Base2::foo(){...} 
} 

Там может быть страшным, ужасным, удивительным образом объединить эти два подхода, но я не Не думаю, что это действительно поможет при использовании кода. Я могу вернуться к вам.

+0

Я не понимаю, что вы делаете, но квалифицированное имя не может быть использовано для объявления функции-члена как: 'double Base1 :: foo() {...} ' – curiousguy

 Смежные вопросы

  • Нет связанных вопросов^_^