Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Простейший шаблон


Автор: EvgenZ 3.8.2006, 17:41
Знаю, что все просто, но сообразить не могу. Объясните пожалуйста где ошибка и из-за чего. Как исправить...

Код

#include <iostream>
class Animal{
public:
    Animal():mAge(0),mWeigh(0){}
    Animal(int Age, int Weigh): mAge(Age), mWeigh(Weigh){}
    ~Animal(){}
    int GetAge()const {return mAge;}
    void SetAge(int Age){mAge=Age;}
    int GetWeigh()const {return mWeigh;}
    void SetWeigh(int Weigh){mWeigh=Weigh;}
    friend std::ostream& operator<< (std::ostream&, Animal&);
private:
    int mAge;
    int mWeigh;
};

std::ostream& operator<<(std::ostream& Astream, Animal& Ani){
    Astream << Ani.GetAge();
    Astream << Ani.GetWeigh();
    std::cout<<"Animal<<";
return Astream;
}

template <class T>
class Array{
public:
    Array(int Size=5);
    Array(const Array&);
    ~Array(){delete [] pTipe; }
    Array& operator=( Array&);
    int GetSize(){return mSize;}
    void SetSize(int Size){mSize=Size;}
    template <class T>
    friend std::ostream& operator<< (std::ostream&, Array<T>&);
private:
    int mSize;
    T *pTipe;
};
template <class T>
Array<T>::Array(int Size): mSize(Size){
    pTipe=new T[Size];
    for(int i=0;i<Size;i++) 
        pTipe[i]=0;}

template <class T>
Array<T>::Array( Array& rhs){
mSize = rhs.GetSize();
pTipe = new T[mSize];
for(int i=0;i<rhs.GetSize();i++)
   pTipe[i]=rhs[i];
}

template <class T>
Array<T>& Array<T>::operator=( Array<T>& rhs){
if(this==&rhs)
   return *this;
delete [] pTipe;
mSize = rhs.GetSize();
pTipe= new T[Size];
for(int i=0;i<mSize;i++)
   pTipe[i]=rhs[i];
return *this;
}

template <class T>
std::ostream& operator<< (std::ostream& ArStream, Array<T>& Arr){
for(int i=0;i<Arr.GetSize();i++)
   ArStream << Arr[i];
std::cout<<"template <<";
return ArStream;
}

void zapolnenieInt(Array<int>& Arr){
    for(int i=0;i<5;i++)
        Arr[i]=i*5;
}

void zapolnenieAnimal(Array<Animal>& Arr){
Animal *pAni;
  for(int i=0;i<Arr.GetSize();i++){
     pAni=new Animal(i*10);
     Arr[i]=*pAni;
     delete pAni;
     }
} 

int main(){

Animal a;
Array<int> b;
std::cout<<a<<std::endl;
zapolnenieInt(b);
std::cout<<b;
return 0;
}


компилятор VS2005    smile  smile 

Автор: Void 3.8.2006, 18:15
Сколько секунд ты сэкономил, не набирая пробелы в коде, и сколько потерял я, пытаясь в нём разобраться…

Ошибки:
1) Сигнатура определения конструктора класса Array не соответствовала его объявлению (отсутствовал const).
2) Попытка обращаться к объектам типа Array, как a[index], не определив оператор [] или оператор преобразования к T*.
3) В функции zapolnenieAnimal производится попытка создания объекта типа Animal с одним параметром типа int, в то время как у этого класса есть конструктор без параметров и конструктор с двумя параметрами типа int.

Код с исправлениями:
Код
#include <iostream>
#include <cassert>

class Animal {
public:
    Animal():mAge(0),mWeigh(0){}
    Animal(int Age, int Weigh): mAge(Age), mWeigh(Weigh){}
    ~Animal(){}
    int GetAge()const {return mAge;}
    void SetAge(int Age){mAge=Age;}
    int GetWeigh()const {return mWeigh;}
    void SetWeigh(int Weigh){mWeigh=Weigh;}
    friend std::ostream& operator<< (std::ostream&, Animal&);
private:
    int mAge;
    int mWeigh;
};

std::ostream& operator<<(std::ostream& Astream, Animal& Ani) {
    Astream << Ani.GetAge();
    Astream << Ani.GetWeigh();
    std::cout<<"Animal<<";
    return Astream;
}

template <class T>
class Array {
public:
    Array(int Size=5);
    Array(const Array&);
    ~Array(){delete [] pTipe; }
    Array& operator=( Array&);
    int GetSize(){return mSize;}
    void SetSize(int Size){mSize=Size;}
    T &operator [](int index);
    const T &operator [](int index) const;
    template <class T>
    friend std::ostream& operator<<(std::ostream&, Array<T>&);
private:
    int mSize;
    T *pTipe;
};

template <class T>
Array<T>::Array(int Size) : mSize(Size) {
    pTipe=new T[Size];
    for(int i=0;i<Size;i++) 
        pTipe[i]=0;
}

template <class T>
Array<T>::Array(const Array& rhs) {
    mSize = rhs.GetSize();
    pTipe = new T[mSize];
    for(int i=0;i<rhs.GetSize();i++)
        pTipe[i]=rhs[i];
}

template <class T>
Array<T>& Array<T>::operator=(Array<T>& rhs) {
    if(this==&rhs)
        return *this;
    delete [] pTipe;
    mSize = rhs.GetSize();
    pTipe= new T[Size];
    for(int i=0;i<mSize;i++)
        pTipe[i]=rhs[i];
    return *this;
}

template <class T>
T& Array<T>::operator [](int index) {
    assert(index >= 0 && index < mSize);
    return pTipe[index];
}

template <class T>
const T& Array<T>::operator [](int index) const {
    assert(index >= 0 && index < mSize);
    return pTipe[index];
}

template <class T>
std::ostream& operator<< (std::ostream& ArStream, Array<T>& Arr){
    for(int i=0;i<Arr.GetSize();i++)
        ArStream << Arr[i];
    std::cout<<"template <<";
    return ArStream;
}

void zapolnenieInt(Array<int>& Arr){
    for(int i=0;i<5;i++)
        Arr[i]=i*5;
}

void zapolnenieAnimal(Array<Animal>& Arr) {
    Animal *pAni;
    for(int i = 0; i < Arr.GetSize(); i++){
        pAni = new Animal(); // wtf?!
        Arr[i] =* pAni;
        delete pAni;
    }
} 

int main(){
    Animal a;
    Array<int> b;
    std::cout<<a<<std::endl;
    zapolnenieInt(b);
    std::cout<<b;
    return 0;
}

Автор: EvgenZ 3.8.2006, 18:40
Цитата

Попытка обращаться к объектам типа Array, как a[index], не определив оператор [] или оператор преобразования к T*.

 
это значит, что все шаблонные классы должны содержать оператор [] ? А зачем перегруженный const?

#include <cassert> - что такое?

Автор: Void 3.8.2006, 20:21
Цитата(EvgenZ @  3.8.2006,  20:40 Найти цитируемый пост)
это значит, что все шаблонные классы должны содержать оператор [] ?

Нет. Но в данном случае он необходим, так как объекты класса Array в коде используются в качестве массивов.
Цитата(EvgenZ @  3.8.2006,  20:40 Найти цитируемый пост)
#include <cassert> - что такое?

Заголовочный файл, подключённый для использования макроса assert. RTFM.

Автор: EvgenZ 3.8.2006, 21:57
насчет assert я тупанул  smile , про классы-массивы вроде тоже понял, а вот зачем const [] и просто [] непойму.

Автор: Void 3.8.2006, 22:02
Цитата(EvgenZ @  3.8.2006,  23:57 Найти цитируемый пост)
а вот зачем const [] и просто [] непойму. 

Без варианта с const компилятор не даст вызвать оператор для константного массива. Например, не скомпилируется такой код:
Код
int sum(const Array<int>& a) {
    int result = 0;
    for (int i = 0; i < a.GetSize(); ++i)
        result += a[i];
    return result;
}

Кстати, GetSize в том случае тоже надо сделать константным. Вообще, не надо пренебрегать const: если метод не изменяет состояние объекта, надо делать его константным.

Автор: GePo 3.8.2006, 22:17
Цитата(Void @ 3.8.2006,  23:02)
Цитата(EvgenZ @  3.8.2006,  23:57 Найти цитируемый пост)
а вот зачем const [] и просто [] непойму. 

Без варианта с const компилятор не даст вызвать оператор для константного массива. 

Void, наверное это был вопрос про лишнюю перегрузку оператора []. Посмотри в код, если оставить одну константную перегрузку оператора, то и для обычного объекта метод будет работать.
EvgenZ, естественно, можно оставить только одну константную перегрузку.

Автор: Void 3.8.2006, 22:22
GePo, семантика Array подразумевает необходимость обоих вариантов. Если один из них (или оба) не используются в данной конкретной программе, это ничего не значит.

Автор: GePo 3.8.2006, 22:33
Void, извнияюсь, не доглядел. Если я правильно понял, то под особенностью семантики подразумевается разница в возращаемых типах функциями - в одном случае - ссылка на объект, во-втором - ссылка на константный объект. ( это все-таки для ответа на вопрос EvgenZ)

Автор: EvgenZ 3.8.2006, 22:34
Спасибо большое, у меня была мыслишка написать operator[], но я совершенно не подумал про const []. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)