2016-06-10 3 views
-1

Как изменить тип унаследованной переменной в производном классе? У меня есть следующие классы:переменная upcasting в производном классе C++

class Position; 
class StonePosition; 

class Position { 
public: 
    Position() {} 
}; 

class StonePosition : public Position { 
    int count; 
public: 
    StonePosition(const int count) { this->count = count; } 
    int getCount() { return this->count; } 
    void setCount(int count) { this->count = count; } 
    friend ostream& operator<<(ostream&, StonePosition); 
}; 

class Board { 
protected: 
    Position* crrPos; 
public: 
    Board() { } 
    Position* getCrrPos() { return crrPos; } 
    void setCrrPos(Position* pos) { crrPos=pos; } 
}; 

class StoneBoard : public Board { 
public: 
    StoneBoard(const int &count) { this->crrPos=new StonePosition(count); } //<---------------- 
    StonePosition* getCrrPos() { return (StonePosition*)crrPos; } 
    void setCrrPos(StonePosition* pos) { crrPos=pos; } 
}; 

Место, в котором проблема отмечена стрелкой. Мне нужно изменить тип переменной с позиции на StonePosition в классе StoneBoard. Я нашел вариант, который можно использовать для повышения эффективности, но он работает только в рамках одного метода, и мне нужно изменить переменную для всего класса.

Проблема решена, посмотрите на мой ответ.

+3

'template class TBoard {..}' может помочь. – Jarod42

+1

C++ не является гибким. Вы не можете изменить тип переменной. Вот почему существовали шаблоны https://en.wikipedia.org/wiki/Template_(C%2B%2B) –

+0

Зачем вам нужно менять тип? Кажется, вы могли бы просто «dynamic_cast» в «StonePosition» всякий раз, когда вам это нужно (как вы это делали с 'getCrrPos' – lcs

ответ

0

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

Если вы хорошо проектируете свои классы и используете виртуальные функции, вы можете избежать необходимости полностью взлетать.

#include <iostream> 

class Base { 
public: 
    virtual void foo() { std::cout << "Base::foo()\n"; } 
    virtual bool isDerived() const { return false; } 
}; 

class Derived : public Base { 
public: 
    void foo() override { std::cout << "Derived::foo()\n"; } 
    bool isDerived() const { return true; } 
}; 

int main() { 
    Base* crrPos = new Derived; 
    crrPos->foo(); 
    bool isDerived = crrPos->isDerived(); 
    std::cout << isDerived << '\n'; 
    delete crrPos; 
} 

Живая демонстрация: http://ideone.com/UKcBaA

+0

Ну, с указателем на меня тоже проблема. Например, указатель на класс Position не знает о существовании переменной count. – Nawy

-2

Проблема была решена, я просто использовать проекцию ((StonePosition *) Должность *):

#include <iostream> 
using namespace std; 
class Position; 
class StonePosition; 

class Position { 
public: 
    Position() {} 
}; 

class StonePosition : public Position { 
    int count; 
public: 
    StonePosition(const int count) { this->count = count; } 
    int getCount() { return this->count; } 
    void setCount(int count) { this->count = count; } 
    friend ostream& operator<<(ostream&, StonePosition); 
}; 
template <typename TPos> class TBoard { 
protected: 
    TPos* crrPos; 
public: 
    TBoard() { } 
    TPos* getCrrPos() { return crrPos; } 
    void setCrrPos(TPos* pos) { crrPos=pos; } 
}; 
class Board { 
protected: 
    Position* crrPos; 
public: 
    Board() { } 
    Position* getCrrPos() { return crrPos; } 
    void setCrrPos(Position* pos) { crrPos=pos; } 
}; 

class StoneBoard : public Board { 
public: 
    StoneBoard(const int &count) { this->crrPos=new StonePosition(count); } 
    Position* getCrrPos() { return crrPos; } 
    void setCrrPos(Position* pos) { crrPos=pos; } 
}; 

int main(){ 
    StoneBoard s(7); 
    cout<<((StonePosition*)s.getCrrPos())->getCount();//<----right here 
    system("pause"); 
    return 0; 
} 

И его работы хорошо :)

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