2012-03-12 2 views
1

хорошо - может быть, это глупый вопрос, и гипсовые операторы делают это уже по своей сути ..C++ как определить оператор приведения, который не копирует данные?

Что у меня есть:

  • некоторое внешнее определение класса 4х4 Matrix

  • некоторый собственный 4x4 Матричный класс

оба класса в промежутке просто хранят поплавок [16];

я хотел бы определить в своем классе Matrix оператор произнесения, так что я могу сделать что-то вроде:

MyMatrix4x4 m; 
OtherMatrix4x4(m).someFunctionDefinedInOtherMatrix4x4(); 
SomeFunctionThatTakesOtherMatrix4x4(OtherMatrix4x4(m)); 

И я не хочу этого оператора, чтобы скопировать все данные - функции должны просто работать на том же поплавке [16] данные

Как это сделать?

+1

Вы должны использовать указатели, но я дам C + + профи, давая вам подробности. – ramblinjan

+0

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

ответ

1
OtherMatrix4x4(m) 

Это не оператор литая, это конструкторпреобразования.

Предположим следующее определение MyMatrix4x4:

struct MyMatrix4x4 
{ 
    float x[16]; 
}; 

следующие должны делать это:

struct OtherMatrix4x4 
{ 
    float* x; 
    OtherMatrix4x4(MyMatrix4x4& other) 
    { 
     x = other.x; 
    } 
    void foo() 
    { 
     x[0] = 0; 
    } 
}; 

Для теста:

MyMatrix4x4 a = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}}; 
OtherMatrix4x4(a).foo(); 
cout << b.x[0]; //will output 0, not 1 

EDIT Вот вариант, где вас Не могу изменить другую матрицу:

struct OtherMatrix4x4 
{ 
    float x[16]; 
    void foo() 
    { 
     x[0] = 0; 
    } 
}; 

struct MyMatrix4x4 
{ 
    float* x; 
    operator OtherMatrix4x4() 
    { 
     OtherMatrix4x4 other; 
     x = other.x; 
     return other; 
    } 
}; 

MyMatrix4x4 m; 
OtherMatrix4x4(m).foo(); 
+0

mmmh - но я не могу редактировать OtherMatrix4x4. ok - как насчет (OtherMatrix4x4) (м)? – Mat

+1

@Mat получил, отредактировал мой ответ. –

+0

@Mat отредактирован .... –

3

И я не хочу, чтобы этот оператор копировать любые данные - функции должны просто работать на том же поплавка [16] данных

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

Ну, этого не произойдет. Правила псевдонимов C++ в значительной степени запрещают это.

Вы можете использовать указатели-указатели, чтобы делать «притворяться, что это что-то другое», но вы не можете использовать приведение объектов для этого. Вы можете наложить указатель на объект стека указателем на ваш тип объекта:

MyMatrix4x4 m; 
OtherMatrix4x4 * o = (OtherMatrix4x4 *) &m; 

Однако есть две проблемы. Во-первых, o продлится до тех пор, пока m делает. Это не объект; это указатель на другой объект. Во-вторых, это (вообще) неопределенное поведение (частично из-за нарушения псевдонимов: два несвязанных типа перекрываются). О, скорее всего, это сработает. Но вы находитесь на карте, насколько это гарантирует C++.

Это запах преждевременной оптимизации. Вы действительно думаете, что копирование 16 поплавков - , что большая проблема с производительностью? Если да, то почему бы просто не использовать OtherMatrix4x4 в вашем коде вместо MyMatrix4x4?

+0

Что делать, если у OtherMatrix4x4 есть другие внутренние члены (помощники)? Что делать, если ни один класс не является POD? – Andrei

+1

@ Андрея: Да. А также? Я не уверен, что вы пытаетесь получить здесь. OP предполагает, что эти классы просто 'float [16]' s с некоторыми методами на них. Если это не так, то то, что он хочет, просто невозможно. –

+2

+1 для «запахов преждевременной оптимизации» в дополнение к другим упомянутым материалам. –

0

Просто чтобы представить другое решение, представляющее наследование. Это позволит использовать код, который вы разместили выше. Однако это не оператор трансляции.

class MyMatrix4x4 { 
public: 
    float f; 
}; 

class OtherMatrix4x4 : MyMatrix4x4 { 
public: 
    OtherMatrix4x4(MyMatrix4x4 &matrix) 
    { 
     f = matrix.f; 
    } 

    void someFunctionDefinedInOtherMatrix4x4(); 
}; 
+0

Это все еще делает копию, чего он хотел избежать. Ему действительно нужны два объекта, которые относятся к одной и той же памяти. –

+0

@MooingDuck: вы не можете добавлять участников в существующий объект. Вы не можете просто притвориться, что 'MyMatrix4x4' является' OtherMatrix4x4', только потому, что это производный класс. Новые стандартные правила компоновки C++ 11 * могут * позволить вам сделать это, но C++ 03, конечно же, этого не делает. И вы определенно не можете сделать это так, как он этого хочет, а именно, чтобы экземпляр объекта стал другим экземпляром объекта без копии. –

+0

@NicolBolas: Да, не думал, что на всем пути. Он либо должен сделать класс Matrix без права собственности, либо сделать копию. –

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