C ++ определение члена класса из абстрактного типа - PullRequest
0 голосов
/ 14 сентября 2018

Я пытаюсь переместить некоторый код из C # в C ++, и я пытаюсь найти лучший способ реализовать иерархию классов.В C # в производном классе вы можете определить переменную члена класса из абстрактного типа базового класса.Однако, когда я искал свои ресурсы C ++, кажется, что я могу определить только указатель или ссылочную переменную из абстрактного типа в другом классе (в противном случае компилятор показывает: «не может создать экземпляр абстрактного класса»), но это может иметь проблемы с временем жизни.определенных объектов как время жизни обрабатывается за пределами класса, используя его.Любое предложение о том, как такая иерархия наследования должна быть реализована, когда код C # отображается на C ++?

Class Person
{
  public:
    virtual double getSalary() = 0;
  private:
    int rank;
}

Class Teacher : public Person
{
  public:
     double getSalary();
  private:
     Person manager;        /*<-- Compile error: error C2259: 'Person' : cannot instantiate abstract class */
}

1 Ответ

0 голосов
/ 14 сентября 2018

Прямой ответ на ваш вопрос: вы не можете определить переменную члена класса абстрактного типа. В C ++ член в основном определяется объемом памяти и, поскольку унаследованный класс может требовать другой объем памяти, это невозможно.

Однако вы можете использовать указатели или ссылки.

В вашем случае:

class Teacher : public Person
{
    public:
        double getSalary();
    private:
        Person* manager;
}

Здесь хранится указатель на Person, и, поскольку Teacher is-a Person, объект типа Teacher будет допустимой целью.

Пример использования: мы создаем сеттер

Teacher::set_manager(Person* manager)
{
    this->manager = manager;
}

и назовите это как

Teacher a;
Teacher* b = new Teacher;
a.set_manager(b);

(я использовал сеттер как самый простой пример, не обязательно, потому что я бы рекомендовал так поступать.)

Также возможно:

Teacher a;
Person* b = new Teacher;
a.set_manager(b);

(a должно быть Teacher, хотя, поскольку нам нужен метод set_manager, если мы не хотим разыгрывать)

Еще лучше, кстати, здесь использовать умные указатели. Читайте в std::shared_ptr и связанных с этим. Это будет выглядеть как

std::shared_ptr<Person> manager;

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

Тем не менее, вы, кажется, думаете, что языки более похожи, чем они. Я рекомендую начать с самого начала с базового учебного пособия по C ++, даже если вы оказались опытным программистом C #.

...