Подтвердить что ты не робот

Доступ к родительским защищенным переменным

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

То, о чем я говорю, это:

class Parent {
  protected:
     Parent *target;
     int hp;
}

class Child : public Parent {
  public:
     void my_func();
}

void Child::my_func() {
    target->hp -= 50;
}

Однако, если я попытаюсь скомпилировать это, он будет жаловаться на то, что "hp" является "приватным в этом контексте". Проблема в том, что ребенок не пытается получить доступ к своим родительским переменным, а к другому классу, который может быть или не быть самим ребенком.

Объект может получить доступ ко всем переменным и методам (общедоступным, защищенным или приватным) другого объекта (двух отдельных экземпляров в памяти), который относится к одному классу, поэтому я думал, что он будет работать и с этим, так как он наследует класс, переменные которого он пытается получить, но, похоже, я ошибался в этом.

Любые советы?

P.S. Не быть грубым или чем-то другим, но я знаю, что могу просто создать методы get() и set(), но я надеялся на более чистый способ.

4b9b3361

Ответ 1

Функции-члены определенного класса имеют доступ только к защищенным членам базовых классов, которые фактически являются подобъектами базового класса объектов своего типа класса (или более производных типов).

Члены одного класса не имеют доступа к защищенным членам других экземпляров этого базового класса, поэтому им также запрещено обращаться к защищенным членам через ссылку или указатель на тип базового класса, даже если во время выполнения этот указатель или ссылка могут быть к объекту, который относится к типу класса, чья функция-член пытается получить доступ. Контроль доступа выполняется во время компиляции.

например.

class X
{
protected:
    int z;
};

class Y : X
{
public:
    int f( const Y& y )
    {
        return y.z; // OK
    }

    int g( const X& x )
    {
        return x.z; // Error, Y::g has no access to X::z
    }
};

В вашем примере в выражении target->hp доступ к target является законным, поскольку вы обращаетесь к члену текущего объекта (который имеет тип класса, членом которого является член, Child), но доступ к элементу hp не является законным, поскольку тип target не является указателем на Child, а указателем на Parent.

Ответ 2

Это так просто (что означает очевидное недоразумение OP, потому что люди не тратят время на чтение OP).

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

Или вы можете сделать ребенка другом родительского класса.

Таким образом, любой ребенок имеет доступ к любым переменным родительского элемента, точно так, как вы ожидаете.

class Child;

class Parent {
  protected:
     Parent *target;
     int hp;
     friend void Child::my_func();
}

class Child : public Parent {
  public:
     void my_func();
}

void Child::my_func() {
    target->hp -= 50;
}

Недостатком этого является то, что каждый ребенок может иметь доступ к переменным КАЖДОГО родителя. Однако вы должны учитывать, что в вашем случае компилятор не может знать, что цель Parent * - это тот же экземпляр, что и дочерний. Учитывая, что вы назвали его целевым, я ожидал бы, что иметь доступ ко всем родителям EVERY-родителям - это то, что вы хотите.

Вот еще одна возможность. Попросите всех остальных использовать интерфейс для доступа к родительскому объекту, и только ваш ребенок использует фактический родительский класс. Результат тот же, хотя. Каждый ребенок имеет доступ ко всем переменным родителей.

Вы смешиваете класс с экземпляром. Ребенок имеет доступ к тем же переменным-членам базового класса, которые имеют одну и ту же INSTANCE.

Ответ 3

Хмм, странно, никто этого не упоминал до сих пор, но вы могли бы объявить Ребенка другом Родительского (может быть, потому, что ваш код не совсем ясно, что именно вы хотите здесь сделать)

class Parent {
  friend class Child;
  protected:
     int hp;
}

class Child {
  public:
     void my_func();
     Parent *target;
}

это позволит получить доступ. в качестве альтернативы вы можете написать метод доступа, который public:

class Parent {
public:
  get_hp(){return hp;}
protected:
  int hp;
}

Ответ 4

Попробуйте изменить этот

 Class Child : public Parent