从C ++中的类访问私有变量

时间:2016-01-25 21:46:30

标签: c++ function private

我正在研究一个项目,我想在一个类中声明私有变量,因为我在许多地方读过它比宣布它们公开更好但是如何在main中访问它们?我应该使用什么样的功能来使它们可访问?我想通过一个不是来自main的函数解决系统问题。 那是我的代码到目前为止,

#include <iostream>
#include <limits>

using namespace std;
class Equation

{  
private:

int a1,a2,b1,b2,c1,c2;
   public:

};

int main()
{

int a,b,c,d,e,f;
cout<<"\n"<<endl;
cout<<"                        **** Hello ****               \n\n"<<endl;
cout<<"This is a program to solve a system of equation"<<endl``;
cout<<"Equations will look like a1*x+b1*y=c1"<<endl;
cout<<"and  a2*x+b2*y=c2\n"<<endl;
cout<<"Enter the values for the first equation \n"<<endl;

while ((cout<<"Enter the value of a1 :\n")
 && !(cin >> a)) {
cout << "Invalid input, please enter a number \n"<<endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

while ((cout<<"Enter the value of a2 :\n")
&& !(cin >> b)) {
cout << "Invalid input, please enter a number \n"<<endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

 while ((cout<<"Enter the value of b1 :\n")
 && !(cin >> c)) {
cout << "Invalid input, please enter a number \n"<<endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

 while ((cout<<"Enter the value of b2 :\n")
 && !(cin >> d))  {
cout << "Invalid input, please enter a number \n"<<endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

 while ((cout<<"Enter the value of c1 :\n")
 && !(cin >> e))  {
cout << "Invalid input, please enter a number \n"<<endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

 while ((cout<<"Enter the value of c2 :\n")
 && !(cin >> f))  {
cout << "Invalid input, please enter a number \n"<<endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

cout<< "The first equation is : "<<a<<"x"<<"+"<<c<<"y"<<"="<<e<<"\n"   <<endl;

cout<<"The second equation is : "<<b<<"x"<<"+"<<d<<"y"<<"="<<f<<"\n"<<endl;

double x = ((c*e)-(b*f))/ ((a*e)-(b*d));
double y = ((a*f)-(c*d))/ ((a*e)-(b*d));

cout<<"The solution of the system is "<<"x = "<<x<<"\t"<<"y = "<<y<<"\n\n <<endl;
cout<<"                        **** Thank You ****                 "<<endl;

return 0;
}

6 个答案:

答案 0 :(得分:3)

一个非常不受欢迎的选择是使用setter和getter。

class A {
  public:
    void set_life(int life) { life_ = life; }
    void set_greeting(std::string greeting) { greeting_ = greeting; }
    int get_life() const { return life_; }
    std::string get_greeting() const { return greeting_; }
  private:
    int life_;
    std::string greeting_;
};

这些将以下列方式使用:

int main() {
  A a;
  a.set_life(42); // My object's life_ variable is now 42.
  a.set_greeting("Hello, World!"); // My object's greeting_ variable is now "Hello, World!".

  std::cout << a.get_greeting() << " The meaning of life is " << a.get_life() << '\n';
  // "Hello World! The meaning of life is 42
}

这被认为是一种虚假的错误,因为如果您为每个私有变量引入getter和setter作为规则,那么您也可以公开变量 - 无论如何它们都可以更改。

更好的做法是使用构造函数初始设置变量并创建一个方法来根据变量执行所需的操作 - 程序员不需要知道它们(因此是私有的)。

class A {
  public:
    // Construct life_ with life and greeting_ with greeting
    A(int life, std::string greeting) : life_(life), greeting_(greeting) {}
    void print_message() const { 
        std::cout << greeting_ << " The meaning of life is " << life_ << '\n';
    }
  private:
    int life_;
    std::string greeting_;
};   

现在你的主要看起来像这样:

int main() {
  A a(42, "Hello, World!");
  a.print_message();
}

答案 1 :(得分:3)

正如Paul所提到的,如果你在Equation类中使变量是私有的,那么你不希望除了Equation类之外的任何实体都能访问这些变量。

在这种情况下,你应该使用类的私有成员来解决x和y(因为类成员可以访问类的私有变量),并提供一个公共接口来访问解决系统的结果。

例如:

#include <utility>  // For std::pair

class EquationSolver {
public: 
  EquationSolver(int _a, int _b, int _c, int _d, int _e, int _f)
  : a(_a), b(_b), c(_c), d(_d), e(_e), f(_f), x(0.0), y(0.0) {}

  // This is the interface for solving the equations via method a
  // And allows outside entities to get the result of solving the system
  std::pair<double, double> solveViaMethodA() {
    solveForXInternally();  // This solves for X via the private implementation below
    solveForYInternally();  // This solves for Y via the private implementation below

    // x and y have been updated internally, so they can be returned as the result of the solved system
    return std::make_pair(x, y);
  }
private:
  int a, b, c, d, e, f;
  double x, y;

  // This is an implementation for solving for x 
  void solveForXInternally() {
    x = ((c*e)-(b*f))/ ((a*e)-(b*d));
  }
  // This is an implementation for solving for y 
  void solveForYInternally() {
    y = ((a*f)-(c*d))/ ((a*e)-(b*d));
  }
};

现在您可以使用此类来解决方程式,如下所示:

int main() {
  // Create an instance of the EquationSolver class
  EquationSolver solver(1, 2, 3, 4, 5, 6);

  // Use the instance of the solver to solve the equations
  std::pair<double, double> solved_variables = solver. solveViaMethodA();
}

虽然这个例子说明了使用类来存储求解方程所需的系数,但是没有必要求解单个方程。一个更简洁的解决方案是使用单个函数,如下所示:

#include <utility>

std::pair<double, double> solveSystem(int a, int b, int c, int d, int e, int f) {
  double x = ((c*e)-(b*f))/ ((a*e)-(b*d));  
  double y = ((a*f)-(c*d))/ ((a*e)-(b*d));
  return std::make_pair(x, y);
};

int main() {
  std::pair<double, double> solved_variables = solveSystem(1, 2, 3, 4, 5, 6);
}

然而,使用类允许的是,可以轻松扩展该解决方案。例如,在我提供的EquationSolver类中,如果你想以不同方式求解方程,那么你可以实现额外的私有成员函数来在内部求解x和y,并添加另一个公共成员函数来通过备用方法访问解决方案。 / p>

答案 2 :(得分:3)

当然,了解如何与班级的private进行互动意味着了解privateclass以及所有内容的点,在一个词中概括为"encapsulation," a OOP提供的主要财产。

面向对象编程是关于通过接口相互交互的对象。这些接口为用户提供了改变对象状态的功能。例如,在3D上下文中,可以旋转立方体,可以检索其顶点之一的坐标等 为什么接口?隐藏实现细节。内部变量(private变量)不应该对该对象的任何用户可见。 OTOH,有暴露的变量(标记为public),描述了我所谈论的界面 为了完整起见,我将提到protected,它与派生类共享其下级变量,但这不是这个问题的重点,IMO。
但为何隐藏实施细节?使用户独立于对象的内部结构和状态。用户看不到任何更改,这可以提高可维护性,代码可读性和代码可重用性。

那么,如何继续前进?您需要考虑如何使用Equation类及其内部状态及其暴露。方程由多个变量组成。他们应该是内部状态。它有两面(可能更多)。你需要一些方法来代表它们。方程运算:求解它们?执行等效转换?打印出来?这就是你必须要考虑的事情。

注意:其他人提到过setter和getter。它们分别用于设置和获取对象的成员变量。这很糟糕,因为它们破坏了封装;它们直接改变了对象的状态,违背了OOP的目的,除非试图使可变成员变量看起来不变或控制用自定义代码修改变量,例如。

答案 3 :(得分:1)

面向对象编程的最强大的一个方面是封装,即每个对象以自己的方式处理自己的数据。人们建议将变量声明为私有成员的原因是为了确保该类始终处于有效状态。相信你的课程。给予他们责任,有能力处理自己的系统。

另一个要点是分离关注点。基本上,如果您要采取的操作需要一个对象来更改其变量,那么让对象处理该操作。你实现这一目标的方法是在你的类的公共部分声明一个函数,让你的客户(任何与你的类交互的代码)“request”该类进行更改,让你的类处理那个改变。这是信任你的课程的第二步(我喜欢称之为授权你的课程)。是否需要使用更改数据的类来完成某些操作?让你的班级做。不要让其他实体欺负你的班级,让他们订购你的班级。让他们问,不要求它。

除了所有的笑话,GettersSetters是这种方法的(可以说)恶心的副产品。从技术上讲,让你的课程适合于面向对象编程的方案,因为你为客户提供了一个与你的数据交互的界面。但是,它的工作方式与我们首先拥有访问修饰符的原因相反。像这样的实践在计算机科学中通常被称为anti-patterns,这意味着它是一种变异的,危险的模式形式。我个人认为Getters不好,但Setters是各种令人讨厌的错误的根源。

RobClucas的回答将是我的方向。但是我不是通过构造函数发送数据,而是将输入读取功能带入EquationSolver类。这种方法似乎与您计划首先进行的操作更相似,并且涉及更少的代码更改。

你的课将是这样的:

class EquationSolver {
public:
    void GetEquationParameters() {
        /* This is where your while(cin) blocks are
         You are reading information directly into this class' paramters
         while(cin>>a1)
         while(cin>>a2)
         etc..

        See how you're "asking" this class to read data from the user.
         */

        while ((cout << "Enter the value of a1 :\n")
            && !(cin >> a1)) {
            cout << "Invalid input, please enter a number \n" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }

        while ((cout << "Enter the value of a2 :\n")
            && !(cin >> a2)) {
            cout << "Invalid input, please enter a number \n" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }

        while ((cout << "Enter the value of b1 :\n")
            && !(cin >> b1)) {
            cout << "Invalid input, please enter a number \n" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }

        while ((cout << "Enter the value of b2 :\n")
            && !(cin >> b2)) {
            cout << "Invalid input, please enter a number \n" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }

        while ((cout << "Enter the value of c1 :\n")
            && !(cin >> c1)) {
            cout << "Invalid input, please enter a number \n" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }

        while ((cout << "Enter the value of c2 :\n")
            && !(cin >> c2)) {
            cout << "Invalid input, please enter a number \n" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }
    }

    /*
     * Functions for your client to use to get the final data.
     * Former is the C++ style that returns both values as a pair.
     * Latter is the sweet sweet C style where you fill x and y inside the function.
     * Latter is less data transaction if you care about performance that much.
     */
    std::pair<double, double> SolveEquationSystem() const {
        double x = (b1*c1 - a2*c2) / (a1*c1 - a2*b2);
        double y = (a1*c2 - b1*b2) / (a1*c1 - a2*b2);

        return std::pair<double, double>(x, y);
    }
    void SolveEquationSystem(double * x, double * y) const {
        *x = (b1*c1 - a2*c2) / (a1*c1 - a2*b2);
        *y = (a1*c2 - b1*b2) / (a1*c1 - a2*b2);
    }

    /**
     * Human readable print
     */
    void PrintEquation() {
        cout << "The first equation is : " << a1 << "x" << "+" << b1 << "y" << "=" << c1 << "\n" << endl;
        cout << "The second equation is : " << a2 << "x" << "+" << b2 << "y" << "=" << c2 << "\n" << endl;
    }
private:
    int a1, a2, b1, b2, c1, c2;
};

在主要功能中,这就是你使用它的方式:

void main() {
    cout << "\n" << endl;
    cout << "                        **** Hello ****               \n\n" << endl;
    cout << "This is a program to solve a system of equation" << endl;
        cout << "Equations will look like a1*x+b1*y=c1" << endl;
    cout << "and  a2*x+b2*y=c2\n" << endl;
    cout << "Enter the values for the first equation \n" << endl;

    // Create solver
    EquationSolver solver;

    // Ask solver to get parameters from the user
    solver.GetEquationParameters();
    // Ask solver to print equation in human readable format
    solver.PrintEquation();

    double x, y;
    // Ask solver to do what it's supposed to do
    solver.SolveEquationSystem(&x, &y);

    cout << "The solution of the system is " << "x = " << x << "\t" << "y = " << y << "\n\n" << endl;
    cout << "                        **** Thank You ****                 " << endl;

}

看看我是如何与班级互动的。作为客户main,我要求提供给我的课程以便采取行动。我要求它获取它的将要使用的参数,然后要求它使用它的数据来解决系统。这种方式如果出现错误,则不是关于类;这就是我使用课程的方式。

旁注:尽量不要使用using namespace std。我知道学校教你使用它,但那只是你的老师懒惰。 using namespace x将整个命名空间包含在头文件中,虽然对于小型项目来说并不是什么大问题,但随着项目规模的扩大,它可能会导致一些严重的问题。

如果你真的想要摆脱std::,比如说coutendl,那么你可以使用using std::cout;和{{ 1}}而不是整个命名空间。但是对于非特定功能,我仍然建议您使用using std::endl;(例如,我将其用于std::来指定我不是所有者,我只是使用它)

答案 4 :(得分:0)

你必须为你的班级提供一些公共函数,设置值和返回这些值的其他函数(如果你想知道的话)。

 `
 #include <iostream>  
 #include <limits>

 using namespace std;

    class Equation
    {  
      private:
      int _a1, _a2, _b1, _b2, _c1, _c2;

      public:
      Equation(){ // you can set here default value of variables }
      virtual ~Equation(){}

      void set_eq1(int a, int b, int c){ _a1 = a; _b1 = b; _c1 = c; }
      void set_eq2(int a, int b, int c){ _a2 = a; _b2 = b; _c2 = c; }
      //...
      int get_a1(){ return _a1; }
      int get_a2(){ return _a2; }
      //...

    };


    int main()
    {
       int a, b, c, d, e, f;
       double res1, res2;
       Equation eq;
       cout << "enter value of a: " ;
       cin >> a;
       cout << "enter value of b: " ;
       cin >> b;
       cout << "enter value of c: " ;
       cin >> c;
       eq.set_eq1(a, b, c);
       // and so on...
       res1 = eq.solve_1();
       res2 = eq.solve_2();

      return 0;
    }
`

塞尔吉奥

答案 5 :(得分:-1)

#include <iostream>

using namespace std;
class an
{
    int a=54;
    int b=100;

};

int main()
{
    an f;
    int i;
    void* c=&f;
    for(i=0;i<10;i++)
    {
        cout << "Value is :  " << *reinterpret_cast<int*>(c);
        c++;
    }
    return 0;
}

没有任何功能和简单