Как C ++ инициализирует встроенную переменную через «инициализацию конструктора»? - PullRequest
0 голосов
/ 15 февраля 2020

Я работаю над упражнением, которое мой профессор дал мне на последних экзаменах.

Текст следующий (его перевод, оригинал был на итальянском):

Напишите шаблон класса SmartP<T> интеллектуальных указателей типа T, которые переопределяют назначение, конструктор копирования и деструктор интеллектуальных указателей. Шаблон SmartP<T> должен содержать минимальный интерфейс publi c (с меньшим количеством menbers), который позволяет компилировать следующий код, выполнение вызовет прокомментированную строку

class C {
public:
    int* p;
    C(): p(new int(5)) {}
};

int main() {
    const int a = 1;
    const int *p = &a;
    SmartP<int> r;
    SmartP<int> s(&a);
    SmartP<int> t(s);
    cout << *s << " " << *t << " " << *p << endl; // 1 1 1
    cout << (s == t) << " " << !(s == p) << endl; // 0 1
    *s = 2;
    *t = 3;
    cout << *s << " " << *t << " " << *p << endl; // 2 3 1
    r = t;
    *r = 4;
    cout << *r << " " << *s << " " << *t << " " << *p << endl; // 4 2 3 1
    C c;
    SmartP<C> x(&c);
    SmartP<C> y(x);
    cout << (x == y) << endl; // 0
    cout << *(c.p) << endl; // 5
    *(c.p) = 6;
    cout << *(c.p) << endl; // 6
    SmartP<C> *q = new SmartP<C>(&c);
    delete q;
}

Решение предоставлено мой профессор выглядит следующим образом:

template<class T>
class SmartP{
private:
    T* ptr;
public:
    SmartP(const SmartP& p) { p.ptr!=0 ? ptr(new T(*(p.ptr))) : ptr(nullptr); };
    SmartP(const T* t = 0) { t!=0 ? ptr(new T(*t)) : ptr(nullptr); };
    ~SmartP() { delete ptr;}
    T& operator*() const { return *ptr;}
    bool operator==(const SmartP& p) const { return ptr == p.ptr;}
    SmartP& operator=(const SmartP& p) {
       delete ptr;
       p.ptr!=0 ? ptr(new T(*(p.ptr))) : ptr(nullptr);
       return *this;
    }
};

Но когда я пытаюсь это сделать, я получаю ошибку при каждой «инициализации конструктора», которая говорит:

Тип вызываемого объекта 'C* «не является указателем на функцию или функцию» (обратите внимание, что если я удаляю класс C, я получаю ту же ошибку, но вместо 'C*' появляется 'int *').

Так что я был взволнован по этому поводу, и я дал ему несколько тестов:

    SmartP(const SmartP& p) : ptr(new T(*(p.ptr))) {}; //no error
    SmartP(const SmartP& p) { ptr(new T(*(p.ptr))); }; //error
    SmartP(const SmartP& p) { ptr = new T(*(p.ptr)); }; //no error
    SmartP(const SmartP& p) {
        if(p.ptr!=0){
            ptr(new T(*(p.ptr))); //error
        } else {
            ptr(nullptr);
        }
    };

Поэтому мой вопрос: как C ++ инициализирует встроенную переменную через "инициализацию конструктора"?

Почему если Я инициализирую свою переменную нормально, она работает, но не с помощью «инициализации конструктора»?

1 Ответ

1 голос
/ 15 февраля 2020

ptr(new T(*(p.ptr))); Такая инициализация элемента разрешена только в конструкторе вне его тела, то есть в списке инициализатора элемента. Если вы используете эту строку в теле конструктора, это вызов функции с именем ptr или ptr.operator(). Компилятор говорит, что вы точно такой же, ptr типа C* не является ни функцией, ни функциональным объектом.

Возможны только два способа инициализации ptr, и все эти способы в вашем первом и третьи строки, которые вы отметили как отсутствие ошибок.

Дополнительная информация: Конструкторы и списки инициализаторов элементов

...