简体   繁体   English

如何从另一个类访问私有变量?

[英]How to access private variables from another class?

I'm working on a project in OpenGL, and I have it working in its most basic form. 我正在用OpenGL开发一个项目,并且它以最基本的形式工作。 Now, I need to make it so that my "get" matrices for rotation and orbit are in my Box.cpp file, my speed variables are private, and that I have set functions for those speed variables. 现在,我需要使它的旋转和轨道“获取”矩阵在Box.cpp文件中,速度变量是私有的,并且已经为这些速度变量设置了函数。

I need to access those variables in main, but since they're private, I cannot obviously. 我需要在main中访问这些变量,但是由于它们是私有的,因此我显然不能。

Can someone point me in the right direction? 有人可以指出我正确的方向吗?

main.cpp: main.cpp:

#include "vgl.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#include "Box.h"
#include "Camera.h"
#include "VertexBufferData.h"
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

using namespace std;
using namespace glm;

#define SPACEBAR_KEY 32
#define ESCAPE_KEY 033

Camera* camera;
vector<Box * > gameObjects;
bool keyDown[255];

void CheckKeyboard(){

    if (keyDown['a'])
        camera->RotateLeft();
    if (keyDown['d'])
        camera->RotateRight();
    if (keyDown['w'])
        camera->MoveForward();
    if (keyDown['s'])
        camera->MoveBackWard();
    if (keyDown['e'])
        camera->StrafeRight();
    if (keyDown['q'])
        camera->StrafeLeft();
}

void closeApp()
{
    delete camera;
    for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
        delete (*it);
    }
}


void keyboard(unsigned char key, int x, int y)
{
    switch (key) 
    {
        case ESCAPE_KEY:  // ASCII Escape Key Code
            closeApp();
            exit(EXIT_SUCCESS);
            break;
        default:
            keyDown[key] = true;
    }

    glutPostRedisplay();
}

void keyboardUp(unsigned char key, int x, int y)
{
    keyDown[key] = false;
}

void mouseWheel(int button, int direction, int x, int y)
{

    if (button == 16)
        camera->ResetFOV();
    else if (direction > 0)
        camera->ZoomIn();
    else
        camera->ZoomOut();
}

void mouseMovement(int x, int y)
{
    static bool warp = true;

    if (warp)
    {
        if (x>glutGet(GLUT_WINDOW_WIDTH) / 2)
            camera->RotateRight();
        else if (x<glutGet(GLUT_WINDOW_WIDTH) / 2)
            camera->RotateLeft();

        if (y>glutGet(GLUT_WINDOW_HEIGHT) / 2)
            camera->RotateUp();
        else if (y<glutGet(GLUT_WINDOW_HEIGHT) / 2)
            camera->RotateDown();

        glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
        warp = false;
    }
    else
        warp = true;
}

void timer(int value)
{
    glutPostRedisplay();
    glutTimerFunc(25, timer, 0);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    CheckKeyboard();
    camera->Update();
    for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
        (*it)->shaderProgram->bindShader();
        glm::mat4 MVP = camera->ProjectionMatrix *  camera->ViewMatrix * (*it)->getModelMatrix();
        (*it)->shaderProgram->sendUniform4x4("MVP", glm::value_ptr(MVP));
        (*it)->Draw();
    }
    glutSwapBuffers();
}

void init()
{
    int i = 0;

    camera = new Camera();
    memset(keyDown, false, sizeof(keyDown));

    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
    glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
    glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_CULL_FACE);

    VertexBufferData vertexBufferData = VertexBufferData("Data\\Models\\Objects.xml");

    gameObjects.push_back(new Box(vertexBufferData, glm::vec3(0.0f, 0.0f, 0.0f), "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader"));

    gameObjects.push_back(new Box(vertexBufferData, glm::vec3(4.0f, 0.0f, 0.0f), "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader"));

    gameObjects[1]->rotationSpeed = 5.0f;
    gameObjects[0]->rotationSpeed = 2.5f;
    gameObjects[1]->orbitSpeed = 1.0f;
    //gameObjects[1]->setRotation(45.0f, vec3(0.0f, 0.0f, 1.0f));
    //gameObjects[0]->setScaleMatrix(vec3(2, 2, 2));
    //gameObjects[1]->setOrbitMatrix(vec3(2.0f, 0.0f, 0.0f), 45.0f, 1, 365, 0);
}



int main(int argc, char** argv)
{
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(1024, 768);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutCreateWindow("Satterwhite_Project_3");


    if (glewInit())
    {
        cerr << "Unable to init glew" << endl;
        exit(EXIT_FAILURE);
    }

    init();
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutPassiveMotionFunc(mouseMovement);
    glutMouseWheelFunc(mouseWheel);
    glutTimerFunc(25, timer, 0);
    glutMainLoop();
    return 0;
}

Box.cpp: Box.cpp:

#include "Box.h"

Box::Box(VertexBufferData &vbd,  vec3 initialPosition,const string vertexShader, const string fragmentShader):GameObject(vertexShader, fragmentShader)
{   
    degreesRotated = 0.0f;
    rotationSpeed = 0.0f;
    orbitSpeed = 0.0f;
    Position=initialPosition;
    vertexBufferData =vbd;

    RotationMatrix=mat4(1.0f);
    OrbitMatrix = mat4(1.0f);
    ScaleMatrix=mat4(1.0f);
    TranslationMatrix =translate(glm::mat4(1.0f), Position);

    if (!shaderProgram->initialize())
    {
        std::cerr << "Could not initialize the shaders" << std::endl;
    }

    shaderProgram->bindShader();

    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertexBufferData.verticiesSize, &vertexBufferData.verticies[0], GL_STATIC_DRAW);

    glGenBuffers(1, &fragmentBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, fragmentBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertexBufferData.colorSize, &vertexBufferData.colors[0], GL_STATIC_DRAW);

    shaderProgram->linkProgram();
}
void Box::setRotation(float degrees, vec3 axis)
{
    RotationMatrix = rotate(RotationMatrix, degrees, axis);
}

void Box::setScaleMatrix(vec3 scale)
{
    ScaleMatrix = glm::scale(mat4(1.0f), scale);
}

void Box::setOrbitMatrix(float degrees, vec3 axis)
{
    OrbitMatrix = rotate(OrbitMatrix, degrees, axis);
}

void Box::Draw()
{
    shaderProgram->bindShader();

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(0));

    glBindBuffer(GL_ARRAY_BUFFER, fragmentBuffer);
    glVertexAttribPointer(1, 3, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(0));    

    glDrawArrays(GL_TRIANGLES, 0, vertexBufferData.verticies.size());

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
}

Box.h: Box.h:

#pragma once
#include "GameObject.h"

class Box :  public GameObject
{

private:
    mat4 ModelMatrix;
    mat4 RotationMatrix;
    mat4 OrbitMatrix;
    mat4 TranslationMatrix;
    mat4 ScaleMatrix;
public:
    float rotationSpeed, orbitSpeed, degreesRotated;
    void Draw();
    virtual ObjectType getType() const { return BOX; }

    mat4 getModelMatrix() {return getOrbitMatrix()*TranslationMatrix*getRotationMatrix()*ScaleMatrix;}
    mat4 getRotationMatrix()
    { 
        setRotation(rotationSpeed, vec3(0.0f, 0.0f, 1.0f));
        return RotationMatrix;
    }
    mat4 getTranslationMatrix() {return TranslationMatrix;}
    mat4 getOrbitMatrix()
    {
        setOrbitMatrix(orbitSpeed, vec3(0.0f, 0.0f, 1.0f));
        return OrbitMatrix;
    }
    mat4 getScaleMatrix() {return ScaleMatrix;}
    void setRotation(float degrees, vec3 axis);
    void setScaleMatrix(vec3 scale);
    void setOrbitMatrix(float degrees, vec3 axis);

    Box(VertexBufferData &vertexBufferData, vec3 initialPosition, const string vertexShader, const string fragmentShader);

    vec3 Position;
};
  • if you want to access private and protected members from another class then declare that class you want to access your target class's private and protected members as a "friend class". 如果要从另一个类访问私有成员和受保护成员,则将要访问目标类的私有成员和受保护成员的类声明为“朋友类”。

  • if you want to access private and protected members from main or any other function rather than from a class then declare that function to be a friend of your class like ostream insertion operator "<<" and istream extraction operator ">>" when you overload them in your class to print and input your member data. 如果要从main或任何其他函数而不是从类访问私有成员和受保护成员,则在重载时声明该函数为您的类的朋友,例如ostream插入运算符“ <<”和istream抽取运算符“ >>”他们在您的班级打印和输入您的会员数据。

declaring a class or a function to be friend of your class is like making a new friend in real life whom you trust so you let him/her access your secrets and private stuff so he/she can help you achieve what you find so tough to do yourself but friendship is neither commutative nor associative: "being him/her your friend doesn't mean being you his/her friend because he/she still maybe doesn't trust you thus doesn't declare you to be his/her friend", friend of your father is not your friend. 宣布一个班级或某个职​​能成为班级的朋友,就像在现实生活中结交一个您信任的新朋友一样,这样您就可以让他/她访问您的秘密和私人物品,这样他/她就可以帮助您实现难以做到的目标做自己,但友谊既不能交换也不能交际:“成为他/她的朋友并不意味着成为你的他/她的朋友,因为他/她仍然可能不信任您,因此并没有宣布您成为他/她的朋友”,您父亲的朋友不是您的朋友。

  • the overhead of using friendship is undermining data hiding and encapsulation principles. 使用友谊的开销破坏了数据隐藏和封装原理。 so the law of thumb is to use it cautiously. 因此,经验法则是谨慎使用它。

  • if you want everyone can access your private/protected members then use structs their members are by default public scoped. 如果您希望每个人都可以访问您的私有/受保护成员,则默认使用其成员为公共作用域的结构。 or declare your member data in your class public scoped and this is a very bad design. 或在公共范围内的类中声明成员数据,这是一个非常糟糕的设计。

in this example I'll show you how to access private data from another class and from another function (in this case main function): 在此示例中,我将向您展示如何从另一个类和另一个函数(在本例中为main函数)访问私有数据:

#include <iostream>
#include <string>
using namespace std;


class Foo; // forward declaration
class Bar; // forward declaration

class Foo
{
    public:
        Foo() : MyData(100){}

    private:
        int MyData;
        friend class Bar; // any access scope is ok. Bar will have full access to Foo
        friend int main(); // main now can access private members
};

class Bar // friend of Foo but Foo is not my Friend so it can't access mine
{
    Foo fooObj;

    public:
        Bar(){}
        void PrintFoo()const;
};

void Bar::PrintFoo()const
{
    cout << fooObj.MyData << endl; // accessing private member data of class Foo from Bar
}


int main()
{
    Foo theFoo;
    Bar theBar;
    theBar.PrintFoo();

    cout << theFoo.MyData << endl; // correct! accessing private members of foo from main because main is friend of Foo.

    return 0;
}

In case you do not want to change the protected class you can do this: 如果您不想更改protected class ,可以执行以下操作:

class c0    // this is some class with protected stuff and you do not want or can to change it in any way
    {
public:
    c0(){};
    ~c0(){};
protected:
    int x;
    };
class c1:c0 // this is class just to access c0 stuff without changing its source code
    {
public:
    c1(){};
    ~c1(){};
    int get_x() { return x; }
    void set_x(int new_x) { x=new_x; }
    };
void test()
    {
    c0 a;
    c1 *b=(c1*)(&a);    // access a as c1 type
    b->set_x(1);        // access protected stuff
    }

I often use this to access VCL class stuff without changing it in any way (for example to avoid unnecessary memory transfers and more). 我经常使用它来访问VCL类的东西,而不用任何方式对其进行更改(例如,避免不必要的内存传输等)。

Beware variables and stuff is usually protected for a reason and by changing it in wrong way you may cause unforseen problems like access violation ,memory leaks etc ... so be careful what are you changing with what and at what time. 当心变量和内容通常是出于某种原因而protected ,并且通过错误的方式对其进行更改,可能会导致不可预见的问题,例如访问冲突,内存泄漏等...因此,请注意您在什么时间以及什么时间进行了更改。

But this does not work for private members so for those you need to tamper with the source code to add geters/setters or friends as @Raindrop7 answer suggest. 但这对private成员不起作用,因此对于那些您需要篡改源代码以按照@Raindrop7答案建议添加获取者/设置者或朋友的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM