2016-04-21 2 views
0

У меня есть странная проблема. Я привел пример, объясняющий, в чем проблема. У меня есть 4 класса, которые получают указатель на класс, который присущ 2 другим. Вот как это выглядит: The inherences классов:Собственность класса виртуальная строка не возвращает правильную вещь

class classA{ 
public: 
    classA(){} 
    virtual std::string getType(){return "classA";} 
    classA& operator=(const classA& classa) {return *this;} 

}; 

class classB: public classA { 
    int b; 
public: 
    classB(int n){b=n;} 
    virtual std::string getType() { return "classB"; } 
    void setB(const int b){this->b=b;} 
    int getB() const{return this->b;} 
}; 

class classC: public classA { 
    int c; 
public: 
    classC(int n){c=n;} 
    virtual std::string getType() { return "classC"; } 
    void setC(const int c){this->c=c;} 
    int getC() const{return this->c;} 
}; 

Единственная важная вещь, это getType() функция.

Вот теперь класс, получить указатель на CLASSA

class superClass{ 
    classA* _classA; 
    int nb; 
public: 
    superClass(){nb=0;} 
    void addElement(classA& e){ 
    classA *newTab=new classA[++nb]; // create tab as the same size than the other +1 
    for(int i=0;i<nb-1;i++) 
     newTab[i]=_classA[i]; // add element from the old class to the new one 
    newTab[nb-1]=e; // add the element 
    //delete[] _classA; 
    _classA=newTab; // now copy it to the class 
    //delete[] newTab; 
    } 
    classA* getClass() {return _classA;} 
    int getNb() const{return this->nb;} 

    void displayElements(){ 
    for(int i=0;i<getNb();i++) 
     std::cout << _classA[i].getType() << std::endl; 

    } 
}; 

addElemment() является функция, которая таНос элемента CLASSA с одним пробела более, он наполнен древни элементами, то он добавляет новый элемент, и вот он идет. Это работы, но проблема здесь. Я не использую элемент classA, а только его дочерние элементы. Я хочу добавить элементы класса B и элементы classC суперкласса и получить тип класса с помощью getType(); Вот основной файл

int main(int argc, char const *argv[]) 
{ 
    classB *classb = new classB(9); 
    classC *classc = new classC(10); 

    superClass super; 
    super.addElement(*classb); 
    super.displayElements(); 
    // Display "classA" instead of "classB" 

    super.addElement(*classc); 
    super.displayElements(); 
    // Display "classA" and "classA" instead "classB" and "classC" 

    //std::cout << classb->getType() << std::endl; // return ClassA 
    //std::cout << classc->getType() << std::endl; // return ClassA 

    return 0; 
} 

Я просто хочу, чтобы моя программа отображала правильный класс, один класс. Проблема связана с addElement(), я думаю. Я попытался использовать виртуальный std::string getType()=0;, но он все еще не работает, он ничего не меняет.

Я также попытался не используя шаблон, но ничего не меняется и не работает

Мой вопрос: Я хочу, чтобы моя программа, отображающее дочерний класс вместо CLASSA каждый раз.

+2

Подсказка: __object slicing__ – emlai

+0

Я не знал об этом, я смотрю на это спасибо – Hearner

+0

Я понимаю, что это, но в моем примере я не могу передать адрес superClass, потому что функция уже есть superClass :: superClass() без параметров – Hearner

ответ

1

Вы должны изменить элемент объявления _classA в superClass на следующее: classA ** _classA ;. Так было бы так:

class superClass 
{ 
    classA** _classA; 
    int nb; 
public: 
    superClass():_classA(0) // you also should initialize this to avoid crash while first delete[] of this _classA 
    { 
     nb = 0; 
    } 

    ~superClass() // also you should add destructor to free memory 
    { 
     for (int i = 0; i < nb; i++) 
     { 
      delete _classA[i]; 
      _classA[i] = nullptr; 
     } 
     delete[] _classA; 
     _classA[i] = nullptr; 
    } 

    void addElement(classA& e) 
    { 
     int oldSize = nb; 
     nb++; // increment the size separately for clarity 
     classA **newTab = new classA*[nb]; // create tab as the same size than the other +1 
     for (int i = 0; i < oldSize; i++) 
     newTab[i] = _classA[i]; // add element from the old class to the new one 
     classA* newElement = new classA(e); // use the copy-constructor 
     newTab[oldSize] = newElement; // add the element 
     delete[] _classA; // now you can free it 
     _classA = newTab; // now copy it to the class 
    } 
    classA** getClass() 
    { 
     return _classA; 
    } 
    int getNb() const 
    { 
     return this->nb; 
    } 

    void displayElements() 
    { 
     for (int i = 0; i < getNb(); i++) 
     std::cout << _classA[i]->getType() << std::endl; 

    } 
}; 
+0

Спасибо, используя ** делает трюк. Можете ли вы объяснить мне, почему это работает?Большое спасибо, но я хотел бы знать, почему ^^ – Hearner

+0

'~ superClass() { delete [] _classA; } 'сбой в конце программы (сигнал SIGABRT) – Hearner

+0

Ни в коем случае, если вы правильно инициализировали элемент _classA, то, пожалуйста, посмотрите на конструктор еще раз, чтобы он был «superClass(): _ classA (0)», чтобы избежать такого сбоя , –

0

newTab - это массив classA. Поэтому он не может содержать classB объектов, только classA объектов.

newTab[nb-1]=e; 

Здесь, если e относится к classB объекта, это назначение нарезает classB часть от него, так что он становится classA объектом и может поместиться в массиве. Это называется object slicing.

+0

Спасибо, что нашли время ответить. Я читал об этом, но как этого избежать? Что я должен сделать, чтобы отобразить правильную вещь в моем примере? – Hearner

Смежные вопросы