С++ самостоятельно в списке инициализации

у меня есть этот фрагмент кода

class Osoba{
         Osoba(char* imie,int wiek){                         
                     this->imie=new char[strlen(imie)+1];
                     strcpy(this->imie,imie);
                     this->wiek=wiek;
                     cout<<"Utworzono Osobe "<<this->imie<<endl;
         }
         Osoba(Osoba& x){
                 Osoba(x.imie,x.wiek);
         }
[...]

и когда я вызываю конструктор копирования, он не работает (создает и уничтожает объект).

Изменить: если я использую

         Osoba(Osoba& x): Osoba(x.imie,x.wiek){

я получаю type 'class Osoba' is not a direct base of 'Osoba'

как это делается?


person n00b    schedule 17.05.2011    source источник
comment
Используйте std::string вместо char * для представления строк в C++. Это делает вещи намного проще. Кроме того, ваш заголовок предлагает что-то о списках инициализации, но вы не используете их в коде, который вы показываете.   -  person Björn Pollex    schedule 17.05.2011
comment
http://stackoverflow.com/questions/1598967/benefits-of-initialization-lists   -  person Bo Persson    schedule 17.05.2011
comment
@ c0wb0y я знаю, что это просто для образовательных целей -› почему я использую char * (динамическое выделение памяти и т. Д.)   -  person n00b    schedule 17.05.2011


Ответы (4)


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

Если вам нужно иметь какой-то общий код между конструкторами, вы можете поместить его в отдельный метод и вызвать этот метод. Обратите внимание, что в конструкторе вы можете вызывать методы объекта, но методы virtual не будут отправлять производные классы.

Другими словами, если у вас есть

struct Foo
{
    virtual void doit() { ... }
    Foo() {
        doit();
    }
};

struct Bar : Foo
{
    virtual void doit() { ... }
};

во время конструктора Bar вызываемая реализация doit будет той, которая определена в Foo, потому что во время конструктора базовой части производного объекта объект является только «базовым» объектом. Только в конце конструктора он становится "производным" объектом прямо перед выполнением любого возможного кода в "производном" конструкторе.

Будьте осторожны, чтобы другие объектно-ориентированные языки использовали другой подход...

Чтобы узнать, что именно происходит в C++, см. эту статью.

Если вам нравится вместо этого юридическое описание, это то, что указано в стандарте С++ в 12.7.4:

Функции-члены, включая виртуальные функции (10.3), можно вызывать во время построения или уничтожения (12.6.2). Когда виртуальная функция вызывается прямо или косвенно из конструктора (в том числе из мем-инициализатора для члена данных) или из деструктора, а объект, к которому применяется вызов, является строящимся или уничтожаемым объектом, вызываемая функция является функция, определенная в собственном классе конструктора или деструктора или в одной из его баз, но не функция, переопределяющая ее в классе, производном от класса конструктора или деструктора, или переопределяющая ее в одном из других базовых классов самого производного объекта (1.8 ). Если вызов виртуальной функции использует явный доступ к члену класса (5.2.5), а выражение-объект ссылается на строящийся или уничтожаемый объект, но его тип не является ни собственным классом конструктора, ни деструктора, ни одним из его базовых элементов, результат вызов не определен.

person 6502    schedule 17.05.2011
comment
я приму это, потому что это очень полезно :) быстрые и неприятные хаки - это то, что мне нравится. - person n00b; 17.05.2011
comment
Я думаю, что во время конструктора Bar реализация вызываемого doit будет той, что определена в Foo, не совсем верно. Стандарт так говорит? Разве это не не указано/не определено? - person Nawaz; 17.05.2011
comment
@Nawaz: я не могу найти это в стандарте, но поиск в формате pdf отстой (а поиск версий мертвого дерева еще сложнее ;-)). Я все равно добавил ссылку на объяснение точной динамики. Я ясно помню, как читал об этом из авторитетного источника, когда изучал C++ (но это было много лет назад, поэтому я точно не помню, что это был за источник... вероятно, TCPPPL). - person 6502; 17.05.2011

Вы не можете вызывать такие конструкторы. Ну, вы можете, но происходит то, что создается безымянный временный объект. Напишите свой конструктор копирования без ссылки на другой конструктор. Кроме того, если вы используете std::string вместо char *, вам не понадобится конструктор копирования. Если вы настаиваете на использовании char *, вам также понадобятся деструктор и оператор присваивания.

person Community    schedule 17.05.2011
comment
вы на 100% уверены, что не можете повторно использовать другие конструкторы?, и да, у меня есть деструктор, который я знаю о строке :) - person n00b; 17.05.2011
comment
@noob Вы не можете повторно использовать другие конструкторы, но иногда вы можете выделить код в частную функцию-член, не являющуюся конструктором. - person ; 17.05.2011
comment
@noob: и не забудьте правильно определить конструктор копирования: Osoba(const Osoba& x) - person Kirill Kovalenko; 17.05.2011

Вы должны инициализировать члены Osoba так же, как вы делаете это в другом конструкторе.

Вы можете повторно использовать конструкторы (с другим синтаксисом) только в C++ 2011.

person Didier Trosset    schedule 17.05.2011

Во-первых, конструктор — это не просто метод, который нельзя просто использовать как метод-мутатор.

что сказал: «Правильно ли я думаю, что в вашем классе было два поля, imie и wiek?»

просто повторите код инициализации, на этот раз с x.imie и x.wiek в качестве входных данных

person Martin Kristiansen    schedule 17.05.2011