2010-09-28 3 views
1

Я пытаюсь создать новый пользовательский тип данных, который ведет себя как все остальные примитивные типы. В частности, этот тип данных появляется как фракция с фиксированной точкой. Я создал класс, представляющий этот тип данных, называемый «класс FixedPoint», и в нем есть способы приведения типов от «FixedPoint» к «int» или «double» или «unsigned int» и т. Д. Это прекрасно ,C++: Пользовательский тип данных - проблемы с типом и объединением

Теперь, что, если я хочу бросить от "int" to "FixedPoint"? Первоначально мое решение было иметь конструктор:

FixedPoint(int i) { /* some conversion from 'int' to 'FixedPoint' in here */ } 

Это работает ... но вы не можете поместить его в союз, как так:

union { 
    FixedPoint p; 
}; 

Это сломается, потому что «FixedPoint» не имеет неявный тривиальный конструктор (мы просто определили конструктор «FixedPoint (int i)»).

Подводя итог, вся проблема заключается в «мы хотим cast from some type T to type FixedPoint without explicitly defining a constructor, чтобы мы могли использовать наш тип FixedPoint в союзе».

Что я думаю, что решение есть, но не может найти никаких доказательств в Интернете: Определите перегруженный глобальный оператор типа-типа для перевода из «int» в «FixedPoint».

Есть ли способ сделать это без использования конструкторов классов? Я хотел бы иметь возможность использовать этот класс в союзе. То, что я пытался (в глобальном масштабе):

operator (FixedPoint f, int a) { ... } //compiler complains about this is not a method or non-static. 

И немного пример, чтобы показать профсоюзы не любят конструкторы (они, как POD)

class bob 
{ 
    public: 
    bob(int a) { m_num = a; } 
    private: 
    int m_num; 
}; 
void duck() 
{ 
    union 
    { 
    bob a; 
    }; 
} 

Эта ошибка видели в Visual Studio является:

error C2620: member 'duck::<unnamed-tag>::a' of union 'duck::<unnamed-tag>' has user-defined constructor or non-trivial default constructor 

Любые идеи? Thanks

ответ

0

Мне тяжело видеть, что вы пытаетесь использовать для этого. Кажется, что вонючим приходится постоянно следить за тем, чтобы sizeof(FixedPoint) == sizeof(int) и, предположив, что есть другие скрытые gotchas, такие как endianness. Может быть, мне нужно немного подружиться здесь, профсоюзы только «конвертируют» значение из одного типа в другое, поскольку он занимает кусок памяти и ссылается на него как на другой тип. т.е.

union BadConverter 
{ 
    int integer; 
    double fraction; 
}; 

BadConverter.fraction = 100.0/33.0; 
BadConverter.integer = ?; 

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

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

class FixedPoint 
{ 
    FixedPoint& operator=(int value); 
    FixedPoint& operator=(double value); 
    ..etc.. 
    //Maybe something like this? 
    template<typename T> 
    FixedPoint& operator=(const T& value) 
    { 
     value = boost::lexical_cast<int>(value); 
     return *this; 
    } 
} 
+0

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

+0

@Ootawata: Если вы удовлетворены ответом, вы должны его принять. – messenger

+0

Чтобы действительно обернуть это, я сделал кучу глобальных функций, которые использовали разные типы (int, double, float, short и т. Д.), Где каждый возвращал тип FixedPoint. Невозможно применить тип к фиксированной точке - вы должны вызвать одну из глобальных функций. Это позволило мне сохранить класс как обычный стиль данных для использования в союзах. – Ootawata

0

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

EDIT: Я переработал пример использования union, так как это то, о чем вы просили.

EDIT2: Смотрите ниже, если вы пытаетесь пойти в другую сторону (строительство) и не хотите конструкторов.

#include <string> 
#include <sstream> 
using namespace std; 

class FixedPoint 
{ 
public: 
    operator std::string() const 
    { 
     stringstream ss; 
     ss << x_ << ", " << y_; 
     return ss.str(); 
    } 
    int x_, y_; 
}; 

union Items 
{ 
    FixedPoint point_; 
    int val_; 
}; 

int main() 
{ 
    Items i; 
    i.point_.x_ = 42; 
    i.point_.y_ = 84; 
    string s = i.point_; 
} 

Если вы пытаетесь пойти другим путем - например, от int к FixedPoint в моем примере - тогда нормальный способ сделать это на самом деле использовать конструктор преобразования. Учитывая, что вам не нужен нетривиальный конструктор, вы должны прибегнуть к функции преобразования.

FixedPoint make_fixed_point(int x, int y) 
{ 
    FixedPoint ret; 
    ret.x_ = x; 
    ret.y_ = y; 
    return ret; 
} 

union Items 
{ 
    FixedPoint point_; 
    int val_; 
}; 


int main() 
{ 
    Items i; 
    i.point_ = make_fixed_point(111,222); 
} 
+0

Я думаю, что ОП вопрос о конверсии конструкторах не операторы преобразования, то есть он хочет х = не = ху –

+0

@Eugen Constantin Dinca: Ах, спасибо. Будет обновлять сообщение. –

-2

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

Например:

class bob 
{ 
    public: 
    bob(int a=0) { m_num = a; } 
    private: 
    int m_num; 
}; 
void duck() 
{ 
    union 
    { 
    bob a; 
    }; 
} 

Давая a=0 по умолчанию, он должен быть в состоянии поставить в союз. Впрочем, я сам не пробовал.

+0

Это все еще определенный пользователем конструктор ... –

+0

Вы не можете иметь объекты с нетривиальными конструкторами в объединениях. Возможно, вам следовало бы попробовать это? –

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

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