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

C++ 如何从另一个类访问私有变量?,c++,variables,opengl,private,C++,Variables,Opengl,Private,我正在用OpenGL做一个项目,我让它以最基本的形式工作。现在,我需要使旋转和环绕的“get”矩阵在Box.cpp文件中,速度变量是私有的,并且我已经为这些速度变量设置了函数 我主要需要访问这些变量,但由于它们是私有的,我显然无法访问 有人能给我指出正确的方向吗 main.cpp: #include "vgl.h" #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm

我正在用OpenGL做一个项目,我让它以最基本的形式工作。现在,我需要使旋转和环绕的“get”矩阵在Box.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;
}
  • 如果要从另一个类访问私有和受保护的成员,请将要访问目标类的私有和受保护成员的类声明为“朋友类”

  • 如果您希望从main或任何其他函数而不是从类访问私有和受保护的成员,那么当您在类中重载该函数以打印和输入成员数据时,请将该函数声明为类的朋友,如ostream插入运算符“”

宣布一个类或函数为你的类的朋友就像在现实生活中结交一个你信任的新朋友,这样你就可以让他/她访问你的秘密和私人资料,这样他/她就可以帮助你实现你发现自己很难做到的事,但友谊既不是交换的,也不是联想的:“成为他/她你的朋友并不意味着成为你他/她的朋友,因为他/她可能仍然不信任你,因此不会宣布你是他/她的朋友”,你父亲的朋友不是你的朋友

  • 使用友谊的开销破坏了数据隐藏和封装原则,因此经验法则是谨慎使用

  • 如果您希望每个人都可以访问您的私有/受保护成员,那么请使用结构。默认情况下,它们的成员是公共范围的。或者在类中声明您的成员数据是公共范围的,这是一种非常糟糕的设计

在本例中,我将向您展示如何从另一个类和另一个函数(在本例中为main函数)访问私有数据:

#包括
#包括
使用名称空间std;
类Foo;//转发声明
类Bar;//转发声明
福班
{
公众:
Foo():MyData(100){}
私人:
int MyData;
friend class Bar;//任何访问范围都可以。Bar将拥有对Foo的完全访问权限
friend int main();//main现在可以访问私有成员
};
类栏//Foo的朋友,但Foo不是我的朋友,因此它无法访问我的朋友
{
福福吉;
公众:
Bar(){}
void PrintFoo()常量;
};
空栏::PrintFoo()常量
{

cout如果您不想更改受保护的
,可以执行以下操作:

class c0//这是一个包含受保护内容的类,您不希望或无法以任何方式更改它
{
公众:
c0(){};
~c0(){};
受保护的:
int x;
};
类c1:c0//这是一个只访问c0内容而不更改其源代码的类
{
公众:
c1(){};
~c1(){};
int get_x(){return x;}
空集_x(int new_x){x=new_x;}
};
无效测试()
{
C0A;
c1*b=(c1*)(&a);//以c1类型访问a
b->set_x(1);//访问受保护的内容
}
我经常使用它来访问VCL类内容,而不以任何方式进行更改(例如,为了避免不必要的内存传输等)

注意变量和内容通常受到保护是有原因的,如果以错误的方式更改变量和内容,可能会导致无法预见的问题,如访问冲突、内存泄漏等。因此,请注意更改内容和时间


但是这不适用于
private
成员,因此对于那些需要修改源代码以添加geter/setter或好友的成员,正如
@Raindrop7
答案所建议的那样。

这表明了一个严重的设计缺陷。成员是私有的(理论上)是有原因的.我知道,但项目分配给我的人希望这样做。据我所知,访问类中的私有变量的唯一方法是在类中具有可以读取或修改私有变量的私有函数的helper函数。@user1335175您能给我举个例子吗?友谊是什么?可能吗用一些“get,set”函数来解决我的问题?这就是我一直试图解决的方法。天哪,我得到了它。非常感谢你。你是个救命恩人。@艾丹,如果它能解决问题,你应该接受这个答案。(点击计票旁的复选框)。@Raindrop7你需要添加
@nick
来通知用户
nick
,否则他不会知道你添加了评论(除非是该线程的作者)。这是答案,所以作者就是你。此外,此通知仅适用于你在main()中评论的线程上的用户正如我上面所做的,friend将是非常关键和危险的。相反,使用setter和getter是解决方案。friend函数应该不是main函数。
#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);
}
#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;
};
#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;
}