Подскажите пожалуйста, как правильно сделать уникальный идентификатор для экземпляров класса, чтобы он сохранялся и при наследовании?
Пытаюсь делать так:
class a
{
public:
a(void) {
id0++;
id = id0;
}
static int id0;
int id;
}
int a::id0 = 0;
class b : public a
{
}
a ex1; // в ex1 id равен 1
b ex2; // в ex2 id равен 0 ?? почему так и как сделать чтобы был равен 2 ?
Этого не может быть. В приведенном коде ошибки нет.
#include <iostream>
struct a
{
public:
a(void) {
id0++;
id = id0;
}
static int id0;
int id;
};
int a::id0 = 0;
struct b : public a
{
};
int main() {
a ex1;
b ex2;
std::cout << "A: " << a.id << "B: " << b.id << "\n";
}
A: 1B: 2
Ищи ошибку где-то еще. Например, у тебя не покрыт конструктор копирования.
Здравствуйте, Vamp, Вы писали:
V>Этого не может быть. В приведенном коде ошибки нет.
V>Ищи ошибку где-то еще. Например, у тебя не покрыт конструктор копирования.
Здравствуйте, pivcorp, Вы писали:
P>Здравствуйте, Force_Majeure, Вы писали:
F_M>>ActionObject::ActionObject(void)
P>ActionObject::ActionObject(void):Object() P>{ P>//... P>}
Да, так Id присваивается!
Будь другом, разъясни пожалуйста, как это работает? Я думал, что через двоеточие можно только давать значения по умолчанию параметрам в конструкторе, если сам конструктор с параметрами.
В следующих наследниках от ActionObject я должен буду всю цепочку классов развернуть через двоеточие или хватит только непосредственного предка?
Здравствуйте, Force_Majeure, Вы писали:
F_M>Здравствуйте, pivcorp, Вы писали:
P>>Здравствуйте, Force_Majeure, Вы писали:
F_M>>>ActionObject::ActionObject(void)
P>>ActionObject::ActionObject(void):Object() P>>{ P>>//... P>>}
F_M>Будь другом, разъясни пожалуйста, как это работает? Я думал, что через двоеточие можно только давать значения по умолчанию параметрам в конструкторе, если сам конструктор с параметрами.
Это называется список инициализации. В коде который ты показал сначала как якобы ошибочный
был конструктор автоматически сгенеренный компилятором, так как твоего конструктора не было.
Автоматически компилятор сгенерил код который предка инициализирует.
В реальном коде явно прописан конструктор, а значит что ты написал то и будет, т.е. если
нет инициализации она и не произойдет.
В этом конструкторе ты не инициализировал предка. Соответственно конструктор предка не вызывался.
F_M>В следующих наследниках от ActionObject я должен буду всю цепочку классов развернуть через двоеточие или хватит только непосредственного предка?
Если конструктор предка инициализирует своего предка достаточно инициализировать одного.
Т.е.
class A0
{
public:
A0()
{
//some code
}
};
class A1 : public A0
{
public:
A1():A0(){}
};
class A2 : public A1
{
public:
A2():A1(){}
};
A3 a; //some code вызовется здесь
P>Это называется список инициализации. В коде который ты показал сначала как якобы ошибочный P>был конструктор автоматически сгенеренный компилятором, так как твоего конструктора не было. P>Автоматически компилятор сгенерил код который предка инициализирует. P>В реальном коде явно прописан конструктор, а значит что ты написал то и будет, т.е. если P>нет инициализации она и не произойдет. P>В этом конструкторе ты не инициализировал предка. Соответственно конструктор предка не вызывался.
Неправда. Дефолтный конструктор вызывается всегда. Инициализация нужна, чтобы вызвать конструктор, отличный от дефолтного. И в твоем примере списки инициализации не нужны.
Здравствуйте, Vamp, Вы писали:
P>>Это называется список инициализации. В коде который ты показал сначала как якобы ошибочный P>>был конструктор автоматически сгенеренный компилятором, так как твоего конструктора не было. P>>Автоматически компилятор сгенерил код который предка инициализирует. P>>В реальном коде явно прописан конструктор, а значит что ты написал то и будет, т.е. если P>>нет инициализации она и не произойдет. P>>В этом конструкторе ты не инициализировал предка. Соответственно конструктор предка не вызывался. V>Неправда. Дефолтный конструктор вызывается всегда. Инициализация нужна, чтобы вызвать конструктор, отличный от дефолтного. И в твоем примере списки инициализации не нужны.
Допустим я ошибся, вполне вероятно.
Вопрос, а Object::Object(void) в коде не дефолтный конструктор?
Тогда интересно Ваше объяснение почему не работало и вдруг
заработало после добавления конструктора предка в список инициализации
P>Вопрос, а Object::Object(void) в коде не дефолтный конструктор?
Дефолтный. P>Тогда интересно Ваше объяснение почему не работало и вдруг P>заработало после добавления конструктора предка в список инициализации
Не знаю. Думаю, что дело там совсем в другом.
Здравствуйте, Vamp, Вы писали:
P>>Вопрос, а Object::Object(void) в коде не дефолтный конструктор? V>Дефолтный. P>>Тогда интересно Ваше объяснение почему не работало и вдруг P>>заработало после добавления конструктора предка в список инициализации V>Не знаю. Думаю, что дело там совсем в другом.
Поскольку правы Вы (я проверил), а код он привел, интересно все же узнать
почему изменение которое предложил я сработало.
Здравствуйте, AlexCrush, Вы писали:
AC>Так что в чем то другом проблема. AC>Несмотря на то, что предложенное pivcorp решение как-то вам помогло, советую все же разобраться в проблеме глубже.
(Проверим телепатию)
А нет ли там случайно виртуального наследования?
class A {}
class B1 : public virtual A {}
class B2 : public virtual A {}
class C : public B1, public B2 {}
> int main() { > > a ex1; > b ex2; > > std::cout << "A: " << a.id << "B: " << b.id << "\n"; > }
Наверное ex1.id и ex2.id. И сорри за offtop, может подскажешь, почему
под linux данный пример успешно компилируется вот так:
c++ static_var.cpp -o static_var
но выдает кучу ошибок при такой компиляции:
demas@arch ~/sources/study/cpp/oop $ gcc static_var.cpp -o static_var
/tmp/ccfaAbgX.o: In function `main':
static_var.cpp.text+0x36): undefined reference to `std::cout'
static_var.cpp.text+0x3b): undefined reference to
`std::basic_ostream<char, std::char_traits<char> >& std::operator<<
<std::char_traits<char> >(std::basic_ostream<char,
std::char_traits<char> >&, char const*)'
static_var.cpp.text+0x47): undefined reference to
`std::basic_ostream<char, std::char_traits<char> >::operator<<(int)'
static_var.cpp.text+0x57): undefined reference to
`std::basic_ostream<char, std::char_traits<char> >& std::operator<<
<std::char_traits<char> >(std::basic_ostream<char,
std::char_traits<char> >&, char const*)'
static_var.cpp.text+0x63): undefined reference to
`std::basic_ostream<char, std::char_traits<char> >::operator<<(int)'
static_var.cpp.text+0x73): undefined reference to
`std::basic_ostream<char, std::char_traits<char> >& std::operator<<
<std::char_traits<char> >(std::basic_ostream<char,
std::char_traits<char> >&, char const*)'
/tmp/ccfaAbgX.o: In function
`__static_initialization_and_destruction_0(int, int)':
static_var.cpp.text+0xa2): undefined reference to
`std::ios_base::Init::Init()'
static_var.cpp.text+0xa7): undefined reference to
`std::ios_base::Init::~Init()'
/tmp/ccfaAbgX.o.eh_frame+0x12): undefined reference to
`__gxx_personality_v0'
collect2: выполнение ld завершилось с кодом возврата 1
Posted via RSDN NNTP Server 2.1 beta
Re[3]: как сделать уникальный идентификатор?
От:
Аноним
Дата:
31.07.09 05:50
Оценка:
Здравствуйте, DemAS, Вы писали: DAS>под linux данный пример успешно компилируется вот так: DAS>c++ static_var.cpp -o static_var DAS>но выдает кучу ошибок при такой компиляции: DAS>
DAS>demas@arch ~/sources/study/cpp/oop $ gcc static_var.cpp -o static_var
DAS>/tmp/ccfaAbgX.o: In function `main':
DAS>static_var.cpp.text+0x36): undefined reference to `std::cout'
Потому что надо линковаться с плюсовой стандартной библиотекой. Вариантов два:
1) вызывать g++ — он сам разберется, где находится нужная ему libstdc++
2) указывать явно: gcc static_var.cpp -o static_var -lstdc++
Здравствуйте, WeCom, Вы писали:
WC>Здравствуйте, AlexCrush, Вы писали:
AC>>Так что в чем то другом проблема. AC>>Несмотря на то, что предложенное pivcorp решение как-то вам помогло, советую все же разобраться в проблеме глубже.
WC>(Проверим телепатию) WC>А нет ли там случайно виртуального наследования?
WC>class A {} WC>class B1 : public virtual A {} WC>class B2 : public virtual A {} WC>class C : public B1, public B2 {}
Нет, ни виртуального (я, честно, и не знал о таком), ни множественного наследования нет.
Здравствуйте, Ovl, Вы писали:
F_M>>По одному (я в коде не копировал только реализации функций). Без параметров.
Ovl>интересно. Ovl>слушайте, вы можете создать инстанс ActionObject и пройти в дебагере его создание? а затем посмотреть Id сразу после создания
После выполнения конструктора Object id приравнивалось числу, после выполниния конструктора ActionObject — обнулялось. С включенным в список инициализации конструктором Object — не обнулялось. Я сейчас вообще вынес генерацию этого id в отдельный класс. Тогда не обнуляется, даже если не включать в список инициализации конструктор Object.
Здравствуйте, Force_Majeure, Вы писали:
F_M>После выполнения конструктора Object id приравнивалось числу, после выполниния конструктора ActionObject — обнулялось. С включенным в список инициализации конструктором Object — не обнулялось. Я сейчас вообще вынес генерацию этого id в отдельный класс. Тогда не обнуляется, даже если не включать в список инициализации конструктор Object.
Здравствуйте, Fwiffo, Вы писали:
F>Здравствуйте, Force_Majeure, Вы писали:
F_M>>После выполнения конструктора Object id приравнивалось числу, после выполниния конструктора ActionObject — обнулялось. С включенным в список инициализации конструктором Object — не обнулялось. Я сейчас вообще вынес генерацию этого id в отдельный класс. Тогда не обнуляется, даже если не включать в список инициализации конструктор Object.
F>А какой компилятор? Не borland случайно?
Здравствуйте, Force_Majeure, Вы писали:
F_M>Нет, VC++2005
В 2005 этот код работает правильно после минимальных изменений, чтобы компилировалось. Так что ошибка где-то в другом месте. Было бы интересно посмотреть на пример, воспроизводящий ошибку. Непонятно, почему наличие списка инициализации на что-то влияет.
Здравствуйте, Fwiffo, Вы писали:
F>Здравствуйте, Force_Majeure, Вы писали:
F_M>>Нет, VC++2005
F>В 2005 этот код работает правильно после минимальных изменений, чтобы компилировалось. Так что ошибка где-то в другом месте. Было бы интересно посмотреть на пример, воспроизводящий ошибку. Непонятно, почему наличие списка инициализации на что-то влияет.
Здравствуйте, Force_Majeure, Вы писали:
F_M>Я тоже так и не понял причину. Хорощо, что хоть устранилась. F_M>Реальные куски кода из проекта я кидал сюда http://www.rsdn.ru/forum/cpp/3487631.1.aspx
Ага, я этот и компилировал. Вот он на 2005 работает. Т.е. понятно, что список инициализации это затычка, скрывающая настоящую проблему, но интересно было бы понять, почему это что-то меняет. Казалось бы на ассемблерный код это вообще не должно влиять.
DAS>Наверное ex1.id и ex2.id.
Конечно. Опечатка.
DAS>c++ static_var.cpp -o static_var
Наверное, g++?
DAS>demas@arch ~/sources/study/cpp/oop $ gcc static_var.cpp -o static_var
gcc — это с-компилятор. Чтобы компилировать С++ код, используй g++.
Да здравствует мыло душистое и веревка пушистая.
Re[11]: как сделать уникальный идентификатор?
От:
Аноним
Дата:
31.07.09 13:48
Оценка:
Здравствуйте, pivcorp, Вы писали:
P>Поскольку правы Вы (я проверил), а код он привел, интересно все же узнать P> почему изменение которое предложил я сработало.
потому что случаи 1 и 2 отличаются (см. стандарт):
Object o1; //1
Obkect o2(); //2
вы в явном виде указали 2, поэтому заработало, до этого был 1
Re[12]: как сделать уникальный идентификатор?
От:
Аноним
Дата:
01.08.09 19:34
Оценка:
А>потому что случаи 1 и 2 отличаются (см. стандарт): А>
А>Object o1; //1
А>Obkect o2(); //2
А>
Ну да, случаи отличаются: во втором случае объявляется прототип функции, возвращающей Obkect.
P>Это называется список инициализации. В коде который ты показал сначала как якобы ошибочный P>был конструктор автоматически сгенеренный компилятором, так как твоего конструктора не было. P>Автоматически компилятор сгенерил код который предка инициализирует. P>В реальном коде явно прописан конструктор, а значит что ты написал то и будет, т.е. если P>нет инициализации она и не произойдет. P>В этом конструкторе ты не инициализировал предка. Соответственно конструктор предка не вызывался.
Слушайте, я от вас как бы слегка в шоке и в то же время как бы слегка восхищаюсь. Так самоуверенно и убежденно уверять собеседника в том, чего не знаешь — это надо иметь талант, которого у меня, к сожалению, никогда не было.
Здравствуйте, Аноним, Вы писали:
А>Слушайте, я от вас как бы слегка в шоке и в то же время как бы слегка восхищаюсь. Так самоуверенно и убежденно уверять собеседника в том, чего не знаешь — это надо иметь талант, которого у меня, к сожалению, никогда не было.
Это не талант это, рассинхронизация 8). Иной раз думаешь о чем то своем и *вдруг* замечаешь, что уже минут пятнадцать несешь откровенную чушь.
Причем как только сознание регистрирует сразу фиксирует что чушь, но все вокруг внимательно слушают и даже верят пока сами не включат сознание.
В данном случае подсознание высосало из пальца объяснение отталкиваясь от факта который никто кроме него объяснить так и не смог насколько я вижу.
Так что признаю было "уверять собеседника в том, чего не знаешь". НО "самоуверенно и убежденно" отвергаю 8).
А вопрос остается и, коль скоро Вы считаете что знаете (а как еще можно утверждать что не знаю я?),
очень хочется узнать ответ:
Почему исходный код не работал?
Почему мое предложение сработало?