c ++: доступ к членам класса, который содержит класс, который хочет получить доступ - PullRequest
2 голосов
/ 27 января 2012

Возможно ли в c ++ изменить члена класса A, который «окружает» класс B (находится в «верхней» области видимости), кроме использования ссылки на «окружающий класс»?

codeздесь: http://pastebin.com/iEEu9iZG

Цель состоит в том, чтобы изменить переменную GFullScreen тем же значением полноэкранной переменной.Я знаю, что могу передать указатель GFullScreen или ссылку на весь класс Game .. Есть ли другой способ получить к нему доступ?какой из них более эффективен?

Ответы [ 6 ]

2 голосов
/ 27 января 2012

Если член static и public (или если B или функция-член в B для доступа к переменной имеет значение friend из A), тогда да .

В любом другом случае нет.

Причина в том, что B не имеет отношения is-a к A, поэтому вам нужен либо объект (ссылка или указатель), либо все, что вы пытаетесь получить, должно быть static.

EDIT:
Просто для забавы, можно сделать так, чтобы выглядел так, как если бы это было возможно, если дать B отношение has-a к A:

class A
{
    int a;

public:
    struct B;
};

class A::B : private A
{
    void foo() { A::a = 1; }
};

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

2 голосов
/ 27 января 2012

Нет. Это ужасно сломало бы инкапсуляцию. И ссылка в любом случае должна была бы храниться где-то, неявно или явно - как еще вы могли бы запомнить это отношение?

1 голос
/ 27 января 2012

Да.Обратите внимание, что вложенное объединение должно иметь длину не менее 1 байта, поэтому смещение должно быть передано strcpy.Кроме того, поведение этой программы зависит от реализации и является скорее взломом для демонстрационных целей, хотя на практике я ожидал бы, что она будет работать предсказуемо с любым современным компилятором C ++.

#include <cstring>
#include <iostream>

struct _a
{
        union _b {
                void mutate()
                {
                        strcpy(reinterpret_cast<char*>(this) + 1, "Goodbye, World!");
                }
        } b;
        char buf[256];

        _a() { strcpy(buf, "Hello, World!"); }
} a;

int main()
{
        std::cout << a.buf << "\n";
        a.b.mutate();
        std::cout << a.buf << std::endl;
        return 0;
};

Моя точка зрениячто, обладая внутренними знаниями C / C ++, вы можете разработать некоторые зависимые от платформы хаки, которые часто бывают полезны и необходимы.Однако это не так, поэтому я настоятельно не рекомендую использовать приведенный выше код для выполнения обычных задач.

1 голос
/ 27 января 2012

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

0 голосов
/ 14 июля 2016

Итак, я вижу, что никто не ответил на этот пример с лучшим примером, я приведу его здесь:

#include <iostream>
using namespace std;

//before includes:
class A;

//B.h
class B{
    public:
        B(A *);
        void test();
        A *parent;
};

//A.h
class A{
    public:
        A();
        ~A();

        B *b;
        void test();

        int n;
};

//B.cpp
B::B(A *a){
    parent = a;
}

void B::test(){
    cout << parent->n;
}

//A.cpp
A::A(){
    n = 404;
    b = new B(this);
}
A::~A(){
    delete b;
}
void A::test(){
    b->test();
}

//example.cpp
int main( int argc, char **argv){
    A a;
    a.test();
}

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

0 голосов
/ 27 января 2012

В отличие от внутренних (нестатических) Java-классов, внутренние классы C ++ не предоставляют скрытой ссылки на экземпляр внешнего класса (C ++ редко делает что-то скрытое, кроме vtable), поэтому вам нужно предоставить такую ​​ссылку самостоятельно, если это необходимо .

...