Инициализация класса члена с производным классом - PullRequest
0 голосов
/ 22 мая 2018

Поэтому я пытаюсь найти лучший практический способ создания классов-членов на основе их производных классов.

struct A {
    int a = 0
}

struct B : struct A {
    int b = 0;
}
class ContainingClassA {
    ContainingClassA() : member_A(){}

    virtual A get() {
        return member_A;
    }

    A member_A;
}

class ContainingClassB : public ContainingClassA {
    ContainingClassB(){}

    virtual B get() override{
        return member_A;
    }
}

Есть ли способ инициализации member_A в классе ContainingClassBтакой, что это типа B?Я видел, возможно, добавление конструктора к ContainingClassA для инициализации member_A.Я знаю, что мог бы просто объявить переменную B member_B в ContainingClassB и вернуть ее, но, поскольку B является производным от A, кажется, что я мог как-то сохранить ее в унаследованной переменной member_A ...

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Есть ли способ инициализации member_A в классе ContainingClassB таким, чтобы он был типа B?

Нет.member_A является членом ContainingClassA.ContainingClassB использует тот же member_A из родительского класса, ContainingClassA.Вы не можете изменить макет родительского класса.

Также вы не можете изменить объявление виртуальной функции (за некоторыми исключениями).Другими словами, вы не можете переопределить A get() с помощью B get().

Вы можете изменить get(), чтобы вместо него возвращать ссылку , тогда можно будет переопределить A& get() с B& get() (поскольку A& и B& являются ковариантными типами).

Но сначала вам нужно разделить решение на «интерфейс» и две «реализации» для A и B:

#include <iostream>

struct A {
    int a = 0;
};

struct B : public A {
    int b = 1;
};

class ContainingClassBase {
public:
    virtual const A& get() = 0;
};

class ContainingClassA : public ContainingClassBase {
    A member_A;
public:
    virtual const A& get() override { return member_A; }
};

class ContainingClassB : public ContainingClassBase {
    B member_B;
public:
    virtual const B& get() override { return member_B; }
};

int main() {
    ContainingClassA a;
    ContainingClassB b;
    std::cout << a.get().a << std::endl;
    std::cout << b.get().b << std::endl;
}

Обратите также внимание, что решение с выделением A отдельно и сохранением указателя на него не очень эффективно, поскольку трудно избежать выделения ложного A при построении ContainingClassB (конструктор ContainingClassA будет по-прежнему вызываться первым).

0 голосов
/ 22 мая 2018

Вы можете использовать шаблоны, чтобы иметь возможность выбрать тип переменной.Как то так:

#include <iostream>

struct A {
  int a = 0;
};

struct B : A
{
  int b = 0;
};

template<typename T>
class ContainingClassA
{
 public:
  ContainingClassA() : member_A(){}

  virtual T get() {
    return member_A;
  }

  T member_A;
};

class ContainingClassB : public ContainingClassA<B>
{
 public:
  ContainingClassB() { }

  virtual B get() override
  {
    return member_A;
  }
};

int main()
{
  ContainingClassB cb;
  std::cout << cb.get().a;
  std::cout << std::endl;
  std::cout << cb.get().b;
  return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...