2010-10-05 2 views
2

Я работаю с классом, для которого новый оператор был сделан частным, так что единственный способ получить экземпляр, чтобы написатьРазмер экземпляра класса

Foo foo = Foo() 

Запись

Foo* foo = new Foo() 

не работает.

Но потому, что я действительно хочу указатель на него, я имитировать, что со следующим:

Foo* foo = (Foo*)malloc(sizeof(Foo)); 
*foo = Foo(); 

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

Похоже, что это работает, из эмпирических тестов, но возможно ли, что недостаточно было выделено пространством malloc? Или что-то другое становится забавным?

--- редактировать ---

А не говоря контекст, потому что я не был на самом деле уверен, о том, почему они были отключены новый оператор. Этот класс является частью библиотеки программирования ограничений (gecode), и я думал, что она может быть отключена для принудительного документированного способа указания модели.

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

Эта схема размещения может быть прекрасной при указании стандартной модели --- в которой все указано как CDT в классе Space, но в моем случае каждый экземпляр создается определенными классами, а затем передается ссылаясь на конструктор класса, который воспроизводит модель.

О причине я не использую в

Foo f; 
Foo *pf = &f; 

было бы, как делать случай 1 ниже, который бросает «возвращающегося ссылку на локальную переменную» предупреждение

int& f() { int a=5; return a; } // case 1 
int& f() { int a=5; int* ap=&a; return *ap; } 
int& f() { int* ap=(int*)malloc(sizeof(int)); *ap=5; return *ap; } 

это предупреждение исчезает при добавлении указателя в case 2, но я думаю, это потому, что компилятор теряет треки.

Так что единственный вариант левая случай 3 (не говоря уже о том, что дополнительно, ap является членом класса, который будет инициализирован только один раз, когда е называется, будет аннулирована иначе, и это единственная функция, возвращающая ссылаясь на это. Я уверен, что ap в этом случае потеряет смысл из-за того, что компилятор оптимизирует его (может случиться?)

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

+0

Почему вы действительно хотите указатель на него? Не можете ли вы сделать что-то вроде Foo foo = Foo(); Foo * fooPtr = &foo; – Hogan

+0

Возможно, я ошибаюсь, но делать это так странно для меня. Является ли 'delete' частным? В противном случае у вас будет явное 'delete' в вашем коде, но не 'new'. Это будет сложно отслеживать. – John

+0

Почему вы просто не делаете '& foo', чтобы получить адрес объекта? почему вы хотите сделать «malloc»? – Naveen

ответ

4

Будьте осторожны при разрыве идиомы типа данных конкретного типа.

Вы пытаетесь обойти тот факт, что оператор new был закрыт, то есть Concrete Data Type идиома/рисунок. Оператор new, вероятно, был закрыт по определенным причинам, например. другая часть дизайна может зависеть от этого ограничения. Попытка обойти это, чтобы динамически распределить экземпляр класса, пытается обойти дизайн и может вызвать другие проблемы или другое неожиданное поведение. Я бы не предложил попытаться обойти это без тщательного изучения кода, чтобы убедиться, что вы понимаете воздействие на другие части класса/кода.

Бетон Тип данных

Solutions

...

Объекты, представляющие абстракции, которые живут «внутри» программы, тесно связанные с вычислительной моделью, реализацией или языком программирования, должны быть объявлены локальными (автоматическими или статическими) экземплярами или экземплярами-членами. Коллекционные классы (строка, список, набор) являются примерами такого вида абстракции (хотя они могут использовать данные кучи, они сами не являются объектами кучи). Они представляют собой конкретные типы данных - они не являются «абстрактными», но являются конкретными как int и double.

class ScopedLock 
{ 
    private: 
    static void * operator new (unsigned int size); // Disallow dynamic allocation 
    static void * operator new (unsigned int size, void * mem); // Disallow placement new as well. 
}; 
int main (void) 
{ 
    ScopedLock s; // Allowed 
    ScopedLock * sl = new ScopedLock(); // Standard new and nothrow new are not allowed. 
    void * buf = ::operator new (sizeof (ScopedLock)); 
    ScopedLock * s2 = new(buf) ScopedLock; // Placement new is also not allowed 
} 

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

8

Не использовать malloc с классами C++. malloc is diffe арендовать от new в очень важном отношении, что new вызывает конструктор класса, но malloc нет.

Вы можете получить указатель несколькими способами, но сначала спросите себя, почему?Вы пытаетесь динамически распределить объект? Вы пытаетесь передать указатели на другие функции?

Если вы передаете указатели вокруг, вы можете быть лучше передавая ссылки вместо:

void DoSomething(Foo& my_foo) 
{ 
    my_foo.do_it(); 
} 

Если вы действительно нужен указатель (возможно потому, что вы не можете изменить реализацию DoSomething), то вы можете просто взять указатель на автоматический:

Foo foo; 
DoSomething(&foo); 

Если вам необходимо динамически выделять Foo объект, все становится немного сложнее. Кто-то сделал причину new операции private. Наверное, очень веская причина. Там может быть способом завода по Foo как:

class Foo 
{ 
public: 
    static Foo* MakeFoo(); 
private: 
}; 

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

+0

В моем случае нет заводских методов, иначе я бы использовал их и получил оттуда указатель. Экземпляры классов инициализируются как CDT (как пояснил Берт Ф.), поэтому я думаю, что конструктор фактически никогда не вызывается (я проверю это). Поэтому я чувствую себя нормально на данный момент (пока это работает). – Gzorg

0

У меня нет полного понимания базового кода. Если все в порядке, приведенный выше код верен. Достаточно места будет выделено от malloc(), и ничего смешного не произойдет. Но избежать использования странного кода и работы straighforward:

Foo f; 
Foo *pf = &f; 
1

Самое смешное, что произошло бы результаты из конструктора не вызывается для *foo. Он будет работать только в том случае, если это POD (простые встроенные типы для членов + конструктор). В противном случае при использовании назначения это может не сработать правильно, если левая сторона уже не является допустимым экземпляром класса.

Кажется, вы все еще можете правомерно выделить экземпляр в куче с

Foo* p = ::new Foo; 

Чтобы ограничить как можно создать экземпляр класса, вы, вероятно, будет лучше объявить конструктор (ы) частные и только позвольте фабричным функциям вызывать их.

0

Заверните:

struct FooHolder { 
    Foo foo; 
    operator Foo*() { return &foo; } 
};