реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> С++. Ошибка в private-контрукторе, почему то требует default-конструктор
jorikdima
сообщение Jan 8 2007, 22:16
Сообщение #1


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 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
Модераторы, не первый раз уже думаю в какую часть форума писать подобные вопросы. Нет подфорума по общим вопросам программирования (или в системный уровень программирования писать???). Написал тут хотя понимаю - ЦОС непричем.

Спасибо.
Go to the top of the page
 
+Quote Post
makc
сообщение Jan 8 2007, 22:35
Сообщение #2


Гуру
******

Группа: Админы
Сообщений: 3 621
Регистрация: 18-10-04
Из: Москва
Пользователь №: 904



Приведите, пожалуйста, полный код, а то, например, такое:
Код
class A
{
public:
    static A* Init(int i);
private:
    A(int u);
    int r;
};

A* A::Init(int i)
{
    return new A(i);            
}

A::A(int u)
{
    r=u;
}

int main()
{
    A* p=A::Init(6);
    return (int)p;
}

у меня прекрасно компилируется и работает.


--------------------
BR, Makc
В недуге рождены, вскормлены тленом, подлежим распаду. (с) У.Фолкнер.
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jan 8 2007, 23:03
Сообщение #3


тут может быть ваша реклама
*****

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



c new у меня тоже компилируется. blink.gif
Но я изначально пишу для 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 и в ИАРе заработало. biggrin.gif

new - это ведь динамически выделяемая память в heap.
В чем будет разница по сравнению с обычным созданием объекта, а не через new и private конструктор?

Вообще применительно к embedded new нормально испоьзовать? Я вроде понимаю, что если динамически занимать и освобождать память то вроде Memory Management нужен, а если без delete, если только занимать?

Чето я подглюкиваю к вечеру blink.gif cranky.gif
Go to the top of the page
 
+Quote Post
Oldring
сообщение Jan 8 2007, 23:13
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Очевидно, компилятор распарсивает эту строчку как определение локальной переменной с именем i типа A с конструктором умолчания.

Главная ошибка состоит в том, что прежде чем для объекта будет вызван какой-нибудь конструктор, под него должно быть где-то выделено место в памяти компьютера. Если объект создается динамически - это место выделяется оператором new. Операто new может быть переопределен нужным программисту образом - чтобы создавать объект не в куче, а где-то в другом месте. Где именно Вы его хотите разместить? Это главный вопрос для понимания происходящего.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jan 8 2007, 23:29
Сообщение #5


тут может быть ваша реклама
*****

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



Все что мне надо - это контроль количества созданных объектов. Мне не очень хочется усложнять себе жизнь и в первую очередь раздувать код (я и так этого предостаточно сделал на ровном месте) заботясь о расположении объекта в памяти. Пусть он располагается так, как будто он создается глобально. Ведь когда объект располагается глобально я не забочусь о его размещении, это делает компилятор. Тут хочу тоже самое, и без new. Может мои желания и странные. Удивляет собственно тот факт, почему если конструктор без параметров, то все работает как надо? blink.gif
Go to the top of the page
 
+Quote Post
Oldring
сообщение Jan 9 2007, 00:07
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(jorikdima @ Jan 8 2007, 23:29) *
Все что мне надо - это контроль количества созданных объектов. Мне не очень хочется усложнять себе жизнь и в первую очередь раздувать код (я и так этого предостаточно сделал на ровном месте) заботясь о расположении объекта в памяти. Пусть он располагается так, как будто он создается глобально. Ведь когда объект располагается глобально я не забочусь о его размещении, это делает компилятор. Тут хочу тоже самое, и без new. Может мои желания и странные. Удивляет собственно тот факт, почему если конструктор без параметров, то все работает как надо? blink.gif


Если хотите контролировать количество создаваемых объектов - заведите в объекте статической поле типа int и считайте в нем в обычных конструкторе и деструкторе. Только все это от лукавого.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
AndrewKirs
сообщение Feb 9 2007, 17:31
Сообщение #7


Участник
*

Группа: Свой
Сообщений: 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, что и требовалось
}
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Feb 9 2007, 17:33
Сообщение #8


тут может быть ваша реклама
*****

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



Спасибо! Мне понравилась идея. Так и сделаю. Спасибо еще раз.
Go to the top of the page
 
+Quote Post
AndrewKirs
сообщение Feb 9 2007, 17:50
Сообщение #9


Участник
*

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



Всегда пожалуйста.
Go to the top of the page
 
+Quote Post
Pathfinder
сообщение Feb 9 2007, 17:54
Сообщение #10


Местный
***

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



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


--------------------
ADC / DAC LC Filter Designer — Удобный инструмент проектирования LC-фильтров для ЦАП и АЦП
Go to the top of the page
 
+Quote Post
AndrewKirs
сообщение Feb 9 2007, 18:04
Сообщение #11


Участник
*

Группа: Свой
Сообщений: 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{
...
};
Go to the top of the page
 
+Quote Post
Pathfinder
сообщение Feb 11 2007, 11:21
Сообщение #12


Местный
***

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



AndrewKirs,
считать число экземпляров объекта внутри реализации класса - довольно распространенное решение (пример - strings в STL), внешней программе как правило абсолютно не интересно знать, сколько на самом деле экземпляров существует - их количество используется только внутри класса.
В данном случае логичнее было бы не ограничивать количество экземпляров класса, а не позволять создать два экземпляра для одного и того же порта.


--------------------
ADC / DAC LC Filter Designer — Удобный инструмент проектирования LC-фильтров для ЦАП и АЦП
Go to the top of the page
 
+Quote Post
shreck
сообщение Feb 12 2007, 07:25
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 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();
}
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Feb 12 2007, 08:56
Сообщение #14


тут может быть ваша реклама
*****

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



Тема была создана месяц назад, а кучу полезных советов получил сейчас smile.gifsmile.gifsmile.gif Спасибо. Вот про синглетон то я и хотел услышать. Помню, что рассказывали нам про эти "идеологии", но забыл что именно. Спасибо.
Go to the top of the page
 
+Quote Post
AndrewKirs
сообщение Feb 13 2007, 15:30
Сообщение #15


Участник
*

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



Синглетон - красивая идея. Хотя все 3 варианта, предложенных здесь, работать будут. И конечное решение - за архитектором системы, в зависимости от его личных предпочтений и вкусов.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 04:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.01521 секунд с 7
ELECTRONIX ©2004-2016