|
С++. Ошибка в private-контрукторе, почему то требует default-конструктор |
|
|
|
Jan 8 2007, 22:16
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280

|
Добрый день. Наткнулся на непонятную для меня проблему. Сначала делал для MSP430, но под Win на Visual Studio тоже самое, поэтому вопрос связан с общими понятиями C++. Код class A { public: static A* Init(int i); private: A(int u); int r; };
A* A::Init(int i) { A(i); //[b]вот тут ошибка[/b] }
A::A(int u) { r=u; }
void main() { A* p=A::Init(6); } Вот такой вот простецкий код. Хочу сделать private-constructor, так как надо сделать ограничение на количество создаваемых объектов. В статической функции Init провожу проверку (сдесь не написал для наглядности) и если условие выполняется, то вызываю коснструктор, то есть выделяю память. И все у меня здорово, до тех пор пока конструктор был без параметров, все работало как надо. А вот при добавлении параметра к конструктору оба компилятра выдают какую-то неперевариваемую мной ошибку: Код 1. redifinition of formal parameter i 2. "A": no appropriate default constructor available не понимаю, почему он хочет дефолт-конструктор и почему переопределение переменной i? PS Модераторы, не первый раз уже думаю в какую часть форума писать подобные вопросы. Нет подфорума по общим вопросам программирования (или в системный уровень программирования писать???). Написал тут хотя понимаю - ЦОС непричем. Спасибо.
|
|
|
|
|
Jan 8 2007, 23:03
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280

|
c new у меня тоже компилируется. Но я изначально пишу для MSP430 а там без new надо. Разве я не могу там вызвать конструктор. Вот более похожий на оригинал код: Код class A { public: static A* Init(int i); private: A(int u); static A* a[2]; };
A* A::a[2]={0};
A* A::Init(int i) { if (i<2 && i>0 && a[i]==0) { A(i); //если индекс объекта 0 или 1 и он еще не создан, то создаем return a[i]; //в переменной static A* a[2]; лежат адреса созданных объектов } return (A*)0; }
A::A(int u) { a[u]=this; }
void main() { A* p=A::Init(0); } Смысл идеи в следующем - подсчитывать количество созданных объектов и если выше порога не создавать, чтоб нельзя было A t[100]; написать. PS Класс описывает работу UART, а у меня их всего два. )) Можно конечно самому себе сказать - не создавай третий и больше, но.. вобщем тут даже скорее любопытство, почему нельзя вот так? написал и сам задал себе вопрос а почему c new нельзя??? Кстати с new и в ИАРе заработало. new - это ведь динамически выделяемая память в heap. В чем будет разница по сравнению с обычным созданием объекта, а не через new и private конструктор? Вообще применительно к embedded new нормально испоьзовать? Я вроде понимаю, что если динамически занимать и освобождать память то вроде Memory Management нужен, а если без delete, если только занимать? Чето я подглюкиваю к вечеру
|
|
|
|
|
Feb 9 2007, 17:31
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 5-05-06
Пользователь №: 16 804

|
Цитата(jorikdima @ Jan 8 2007, 22:16)  A* A::Init(int i) { A(i); //вот тут ошибка } Не совсем понимаю, что Вы тут хотели написать. Очевидно, создать статический экземпляр А? Скажем так: A* A::Init(int i) { A a(i). return &a; } Но ведь этот экземпляр создается в стеке функции и будет потерян после выхода из нее. А вообще, по-моему, сама идея "некрасивая" - контролировать число объектов какого-то класса из самого этого класса. Я бы на Вашем месте вынес этот контроль на уровень выше: class A { public: A(){} private: A(int u){} int r; }; #define MAX_A_COUNT 2 class B{ private: int iAcount; A ArrayOfA[MAX_A_COUNT]; public: B(){ iAcount = 0;} A * CreateA(); }; A * B::CreateA() { if (iAcount >= MAX_A_COUNT) return 0; return &ArrayOfA[iAcount++]; } void main() { B b; A * a1 = b.CreateA(); A * a2 = b.CreateA(); A * a3 = b.CreateA(); // a3 = 0, что и требовалось }
|
|
|
|
|
Feb 9 2007, 17:50
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 5-05-06
Пользователь №: 16 804

|
Всегда пожалуйста.
|
|
|
|
|
Feb 9 2007, 17:54
|

Местный
  
Группа: Свой
Сообщений: 275
Регистрация: 29-06-05
Пользователь №: 6 400

|
Если ограничение на число экземпляров связано с сущностью, которую представляет класс, логичнее контролировать число экземпляров класса из самого класса. Это можно просто сделать например так: Код A::A() { /* Инициализация локальной статической * переменной выполняется только один раз * при вызове конструктора для первого объекта */ static int instance_counter = 0; /* А вот эта операция будет выполняться при каждом вызове конструктора. */ instance_counter++; if (instance > max_instance_count ) throw int(); }
--------------------
|
|
|
|
|
Feb 9 2007, 18:04
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 5-05-06
Пользователь №: 16 804

|
Цитата(Pathfinder @ Feb 9 2007, 17:54)  Если ограничение на число экземпляров связано с сущностью, которую представляет класс, логичнее контролировать число экземпляров класса из самого класса. Это можно просто сделать например так: Код A::A() { /* Инициализация локальной статической * переменной выполняется только один раз * при вызове конструктора для первого объекта */ static int instance_counter = 0; /* А вот эта операция будет выполняться при каждом вызове конструктора. */ instance_counter++; if (instance > max_instance_count ) throw int(); } Воля Ваша, но некрасиво это как-то... Лучше, логичнее, когде работает один объект, а контролирует его другой. Разделение функций на уровне логики и на уровне кода. В конце концов, этот контролирующий класс можно сделать наследником контролируемого. То есть в моем примере вместо class B{ ... }; будет class B: public A{ ... };
|
|
|
|
|
Feb 12 2007, 07:25
|

Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328

|
Может быть не совсем по теме вопроса, но хочется привести решение похожей задачи из классики. Для того, чтобы ограничить количество создаваемых экземпляров класса одним объектом применяется идеология синглетона: Код В файле Single.h
// класс в виде синглетона class Single { public:
// функция, с помощью которой осуществляется ВЕСЬ доступ // к методам и данным класса. // Пример синтаксиса вызова: Single::instance()->some_function(); static Single* instance();
// Интерфейс класса
void some_function();
private: // закрытые члены и методы.
// объявление данных функций закрытыми предотвращает создание // более чем одного экземпляра класса. Single(int param); ~Single(); // функции ниже не должны реализовываться Single(const Single&); // чтобы нельзя было передавать как параметр функции. Single& operator=(const Single&); // для запрета присваивания одного объекта другому };
В файле реализации Single.c
//------------------------------------------------------------------------------ // Создание и предоставление доступа к единственному объекту // класса без использования динамической памяти //------------------------------------------------------------------------------ Single* Single::instance() { static Single obj(some_param); // благодаря static объект создается единственный // раз при первом обращении к instance() return &Single; }
//------------------------------------------------------------------------------ // Реализация остальных методов класса //------------------------------------------------------------------------------
Пример использования.
int main() { // вызов метода класса Single::instance()->some_function();
// или так Single *inst = Single::instance();
inst->some_function(); }
|
|
|
|
|
Feb 13 2007, 15:30
|
Участник

Группа: Свой
Сообщений: 63
Регистрация: 5-05-06
Пользователь №: 16 804

|
Синглетон - красивая идея. Хотя все 3 варианта, предложенных здесь, работать будут. И конечное решение - за архитектором системы, в зависимости от его личных предпочтений и вкусов.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|