указатель наследования c ++ - PullRequest
1 голос
/ 13 июля 2011

Мне довольно сложно описать мою проблему. У меня есть два класса, я бы сказал, Base_A и Derived_A. Как видно из названий, класс Derived_A является производным от Base_A. Также в моей программе есть два других класса Base_B и Derived_B (также с наследованием). Класс Base_A содержит объект Base_B, а класс Derived_A содержит объект Derived_B.

class Base_A {
public:
    Base_A() {}
    virtual ~Base_A() {}

    Base_B b_;
    Base_B* pointer_;

    void init() {
        b_ = Base_B();
        pointer_ = &b_;
        pointer_->setValue(1);
    }

    void print() {
        pointer_->getValue();

    }
};

class Derived_A: public Base_A {
public:
    Derived_A() {}
    virtual ~Derived_A() {}

    Derived_B b_;
    Derived_B* pointer_;

    void init() {
        b_ = Derived_B();
        pointer_ = &b_;
        pointer_->setValue(2);
        pointer_->increaseValue();
    }
};

class Base_B {
public:
    Base_B() {}
    virtual ~Base_B() {}

    int value_;

    void setValue(int value) {
        value_ = value;
    }

    void getValue() {
        cout << "Base_B: " << value_ << endl;
    }
};

class Derived_B: public Base_B {
public:
    Derived_B() {}
    virtual ~Derived_B() {}

    void increaseValue() {
        value_++;
    }
};

int main() {  
    Derived_A derived_A = Derived_A();
    derived_A.init();
    derived_A.print();

    return 0;
}

Как вы видите, у каждого класса A есть один объект класса B и указатель на этот объект. Моя проблема в том, что когда я вызываю функцию print(), она не принимает Derived_B* pointer_, но пытается получить доступ к Base_B* pointer_, которого не существует. Как я могу сказать в моей программе, что он должен брать указатель в соответствии с классом? Или мне нужно объявить Base_B* pointer_ внутри класса Derived_A как:

Base::pointer_ = pointer_;

Может быть, есть другой метод или алгоритм для моей проблемы?

Большое спасибо.

Ответы [ 2 ]

3 голосов
/ 13 июля 2011

"но попробуйте получить доступ к Base_B* pointer_, которого не существует"

Если DerivedA неправильно инициализирует BaseA, то DerivedA не соответствует правилу "isA" для наследования, и требования к дизайну изменились. На первый взгляд:

  1. Не используйте повторно имена в производном классе, такие как b_, pointer_. Это просто сбивает с толку, и вы не получаете никакой ценности.
  2. Сделать init () виртуальным.
  3. Пусть DerivedA :: init () явно вызывает BaseA :: init ().
  4. Сделать указатель_ виртуальным методом.

Обратите внимание на использование «ковариантных возвращаемых типов» для виртуальных методов.

class BaseA
    {
    public:
       virtual BaseB* pointer() { return &b_; }
       // etc.
    };

class DerivedA : public BaseA
    {
    public:
       virtual DerivedB* pointer() { return &b_; }
       // etc.
    };
0 голосов
/ 13 июля 2011

не будет ли Base_A иметь указатель на Base_B, если когда-либо вызывался Base_A :: init ()?почему бы вам не начать базовый класс?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...