Я не продвинутый программист. Предположим, что существует классический алмаз наследования:Невозможно получить доступ к защищенным переменным-членам большинства базового класса через std :: unique_ptr в алмазе
class Base
class A: virtual public Base
class B: virtual public Base
class Last: public A, public B
Пусть Base
имеет переменную m_x
, что является общим для обоих A
и B
, таким образом, что только один из A
или B
, можно назвать в то время, не и то, и другое (что и нужно). Чтобы обойти эту проблему, это используется:
class Last: public A, public B
{
private:
std::unique_ptr<Base> m_p;
public:
Last(int i)
{
if (i)
m_p = std::unique_ptr<Base>(new A());
else
m_p = std::unique_ptr<Base>(new B());
}
};
Это прекрасно, но теперь m_p->m_x
не может быть доступно больше, потому что он говорит, он защищен, но и A
и B
вызов m_x
в своих конструкторах напрямую, без каких-либо проблем.
Является ли это известным ограничением или это неправильный способ сделать это? Если это неправильно, какие решения есть?
Вот код, основанный на диаграмме нашли here (чуть ниже на странице):
#include <iostream>
#include <memory>
class Power
{
protected:
double m_x;
public:
Power() {}
Power(double x): m_x {x} {}
virtual ~Power() = default;
};
class Scanner: virtual public Power
{
public:
Scanner() {}
Scanner(double x): Power(x) {} // scan document
};
class Printer: virtual public Power
{
public:
Printer() {}
Printer(double x): Power(x) {} // print document
};
class Copier: public Scanner, public Printer
{
private:
std::unique_ptr<Power> m_p;
public:
Copier() {}
Copier(double x, int i)
{
if (i)
m_p = std::unique_ptr<Power>(new Scanner(x));
else
m_p = std::unique_ptr<Power>(new Printer(x));
}
void print() { std::cout << this->Power::m_x << '\n'; }
};
int main(int argc, char *argv[])
{
Copier *copier {new Copier(1.618, 0)};
copier->print();
copier = new Copier(3.14, 1);
copier->print();
return 0;
}
Используя оба this->m_p
и this->Power::m_x
(в соответствии с ответами и комментариями) компилирует, но выход есть 0
.
Чтобы убедиться, что я объяснить это все: не только я совсем новичок, но, учитывая пример выше, oesn't действительно должен оставаться таким образом, если есть другая альтернатива называть Scanner
или Printer
только один за один раз из внутри Copier
. Я не прошу мнения, я понимаю, что это запрещено, но я не буду отвергать их от более опытных пользователей. В конце концов, я учусь.
Я не совсем понимаю, как 'Last' * is-a * A и * is-a * B, но затем * has-a * либо A, либо B ... для меня не имеет смысла. – nvoigt
'm_p' не ваш базовый объект. 'это' есть. –
@CaptainGiraffe Вы имеете в виду, вместо использования 'm_p-> m_x', я должен использовать' this-> m_x'? Я просто заменил 'm_p' на' this', и он компилируется, но, похоже, он не работает. Переменные - 0, все. Не могли бы вы рассказать? –