Курсови проекти

Получена грешка

Получена грешка

от Гергана Тончева -
Number of replies: 1

Здравейте, 
Изпадам в следната ситуация:

template <typename T>
class A {
private:
    struct B {
        T a;
        T b;        
        B (T _a, T _b) {
                a = _a;
                b = _b;
        }
    }

private:
    B<T> myB;   

public:
    A(
T _a, T _b) {
        myB = B(_a, _b);
    }
}

И получавам следната грешка: 
B<T>: no appropriate default constructor available

Нещата се оправят когато към структурата добавя конструктор по подразбиране или смесен, като задам стойности по подразбиране на всички член данни на структурата. 

Как да изчистя този проблем (не желая да имам конструктор по подразбиране).
Проблемът остава дори когато структурата е извън класа, в този смисъл е без значение дали ще е клас или структура.

In reply to Гергана Тончева

Re: Получена грешка

от Дамян Бойчев -
Здравей Гергана,

Грешката се получава, защото при създаването на обект от клас А преди да се изпълни тялото на конструктора на А се извиква конструктира по подразбиране на myB. Тъй като такъв няма, защото си дефинирала собствен конструктор с параметри, се получава грешка при компилиране. Mожеш изрично да извикаш конструктура с параметри ето така.

A(T _a, T _b):myB(_a, _b) { }

При извикването на конструктор, преди да се изпълни кода в тялото му, се извикват всички конструктори по подразбиране на член-данните, ако има такива, и конструктурите по подразбиране на родителските класове, ако класът участва в йерархия на наследяване. Това се случва ако не сме извикали изрично конструктурите. Ако сме извикали изрично някой конкретен конструктор извикването на този по подразбиране ще се прескочи.

struct A {
private:
    struct B {
        int data;
        B() {
            data = 42;
        }
        B(int data) {
            this->data = data;
        }
    };
    B b1;
    B b2;
public:
    A():b2(20) {
        b1.data = 50;
    }
};

В този пример, при конструирането на обект от тип А, за b1 ще се извика конструктора по подразбиране, а за b2 ще се извика конструктура с параметри. След това ще влезем в тялото на конструктура на А и стойността на b1.data ще се промени на 50.

One more thing...

Забелязах, че в B myB подаваш T като аргумент на шаблона. Това би било вярно, ако B не е вложена в А, но тук това е грешка и не би трябвало да се компилира. Структурата B е декларирана в класа А и "вижда" типа Т. Типът Т се знае от аргумента на шаблона на А. А, A и т. н. Пълното изписване на типа на B е А<Т>::B и оттук се вижда, че структурата В не е шаблонна, само класа А е.

Разбира се, нищо не пречи да я направим и нея шаблонна.

template<typename T>
class A {
    template<typename U>
    struct B {
        U a;
        U b;
        B(U _a, U _b) {
            a = _a;
            b = _b;
        }
    };

    B<T> myB;
    B<int> b_int;
    B<double> b_double;
public:
    A(T _a, T _b):myB(_a, _b), b_int(1, 2), b_double(3.14, 2.71) { }
};

И дори нищо не ни пречи да сложим член-данна от тип Т в B.

template<typename T>
class A {
    template<typename U>
    struct B {
        T a;
        U b;
        B(T _a, U _b) {
            a = _a;
            b = _b;
        }
    };

    B<double> myB;
public:
    A(T _a, double _b): myB(_a, _b) { }
};
int main() {
    A<int> obj(42, 3.14);
}

Сега obj.myB.a e int, а obj.myB.b е double.

Поздрави,
Дамян