我是StackOverflow的新手,从一所新学校开始。我希望对任务有一些指导。赋值是计算涉及两个分数的表达式,并输出结果。我已经用我的教科书中的知识工作了几天这个程序,但我想我仍然对如何在一个类中实现函数感到困惑。我知道我想用我的价值做什么,但我很困惑在哪里分配它们。我尝试读取我的值,但在输出时,我得到了垃圾。任何帮助将不胜感激。
#include <iostream>
using namespace std;
class fraction // Fraction class definition
{
int num,
den;
public:
fraction() // default constructor
{
num = 0;
den = 1;
}
void add(fraction f1, fraction f2) // addition fcn
{
num = (f1.num*f2.den) + (f2.num*f1.den);
den = f1.den*f2.den;
}
void subtract(fraction f1, fraction f2) // subtraction fcn
{
num = (f1.num*f2.den) - (f2.num*f1.den);
den = f1.den*f2.den;
}
void multiply(fraction f1, fraction f2) // multiplying fcn
{
num = f1.num*f2.num;
den = f1.den*f2.den;
}
void divide(fraction f1, fraction f2) // dividing fcn
{
num = f1.num*f2.den;
den = f1.den*f2.num;
}
void output()
{
cout << num << "/" << den << endl;
}
}; // end Fraction class
int main()
{ // begin main
fraction result;
fraction n;
fraction d;
int n1, n2, d1, d2 = 0;
char op;
cout << "Please enter an expression containing two fractions:" << endl;
cin >> n1 >> d1 >> op >> n2 >> d2;
switch (op)
{ // begin switch
case '+':
result.add(n, d);
result.output();
break;
case '-':
result.subtract(n, d);
result.output();
break;
case '*':
result.multiply(n, d);
result.output();
break;
case'/':
result.divide(n, d);
result.output();
break;
} // end switch
//fraction f1(n1, d1);
//fraction f2(n2, d2);
} // end main
答案 0 :(得分:1)
实际答案在John3136的第一条评论中给出。因此,我有点挣扎,但终于意识到你可能没有认识到。所以,我会详细说明一下:
在main()
中,您可以这样做:
int n1, n2, d1, d2 = 0;
char op;
cout << "Please enter an expression containing two fractions:" << endl;
cin >> n1 >> d1 >> op >> n2 >> d2;
通过调试器逐步执行,您将意识到这部分程序按预期工作。输入例如
之后1 2 + 3 4
变量将显示以下值:
n1: 1
d1: 2
n2: 3
d2: 4
op: '+'
上的现场演示
进一步步进,程序指针将移至
result.add(n, d);
嗯。您想要添加n
和d
,但调试器会说:
n: { num: 0, den: 1 }
d: { num: 0, den: 1 }
n.num
,n.den
,d.num
和d.den
的值在那里,因为您提供了class fraction
的默认构造函数,它正好影响了这一点。< / p>
那么,您如何将n1
移至n.num
,d1
转移到n.den
,等等?
真正缺少的是class fraction
加载成员num
和den
的构造函数(在这种情况下为n
和d
)具有指定的值。
您可以引入第二个构造函数。在这种情况下,您可以修改(和扩展)现有的,也包括:
class fraction {
private:
int num, den; // numerator, denominator
public:
explicit fraction(int num = 0, int den = 1): num(num), den(den) { }
};
看起来很混乱?我会解释一下:
我给出了构造函数参数,但参数有默认值。
因此,它仍然可以用作默认构造函数。执行fraction a;
将像以前一样构造分数0/1。但是,现在,您也可以fraction b(3, 2);
来构建3/2分数。你甚至可以做fraction d(3);
。这将构建对我来说合理的分数3/1。
我将参数命名为成员。看起来很有趣,可能有点令人困惑,但现在似乎很平常。 (实际上,我在很短的时间内就已经学到了这一点。)但是,编译器会正确理解这一点(即使它是MS的一个)。
我使用explicit
为构造函数添加了前缀。这可以防止构造函数用于隐式转换。 不 explicit
,以下内容也适用:fraction c; c = 1;
,即从class fraction
分配int
。这是一个设计问题,是否要支持这一点。隐式转换可能非常方便,但编译器可能会在您不期望它的地方应用它。我个人习惯于制作几乎所有构造函数explicit
,因为我不想“失去控制”#34;编译器正在做什么。
按照建议修改上述构造函数,然后可以使用您的类,例如:
fraction a(3, 2), b(1, 2);
fraction result; result.add(a, b);
result.output();
现在,它应该打印分数a
和b
的总和。
最后一点:
我认为O&#Neil's暗示运营商超载基本上是合理的。您将在SO中找到代码示例的答案。 (其中一些,由我写。);-)另一方面,运算符重载只是另一个障碍。我不会为此烦恼太多。 (可能是第二个版本......)
最后,我做了一个MCVE来演示上面提到的示例代码:
#include <iostream>
using namespace std;
class fraction {
private:
int num, den; // numerator, denominator
public:
explicit fraction(int num = 0, int den = 1): num(num), den(den) { }
void add(fraction f1, fraction f2) // addition fcn
{
num = (f1.num * f2.den) + (f2.num * f1.den);
den = f1.den * f2.den;
}
void output() { cout << num << "/" << den << endl; }
};
int main()
{
fraction a0;
cout << "fraction a0: "; a0.output();
fraction a(3, 2), b(1);
cout << "fraction a(3, 2): "; a.output();
cout << "fraction b(1): "; b.output();
fraction c; c.add(a, b);
cout << "fraction c = a + b: "; c.output();
// assignment (using default assignment operator)
fraction d; d = c;
cout << "faction d = c; d: "; d.output();
#if 0 // disabled code
// This will work only if constructor is not explicit:
fraction e = 1; e = 1;
cout << "fraction e; e = 1; e: "; e.output();
#endif // 0
// fraction from input
int n1, n2;
cout << "Input n1 n2: "; cin >> n1 >> n2;
fraction in(n1, n2);
cout << "fraction in(n1, n2): "; in.output();
// done
return 0;
}
输入:
123 321
输出:
fraction a0: 0/1
fraction a(3, 2): 3/2
fraction b(1): 1/1
fraction c = a + b: 5/2
faction d = c; d: 5/2
Input n1 n2: fraction in(n1, n2): 123/321
ideone上的现场演示。
在阅读完您的评论之后,我怀疑您是否已经理解了class
和成员函数的概念。我会尽我所能:
您是否知道您的功能add()
是会员功能?正如您在class fraction
中定义的功能一样。这意味着,如果没有对象(即add()
的实例),则无法调用fraction
。
如果将此内容写入main()
函数,则会出现编译错误:
fraction a, b;
fraction::add(a, b);
上的现场演示
该对象是另一个参数,即(非static
)成员函数(如fraction::add()
)的调用迫切需要。可能是,你没有认识到点前面的东西是函数参数,但确实如此。
fraction c; c.add(a, b);
/* ^ ^ ^
* | | +--- 2nd argument
* | +------ 1st argument
* +------------ object (which becomes THE this POINTER inside fraction::add())
*/
因此,fraction.add()
实际上有三个参数。那么,如何访问该对象?为此,C ++提供了一个特殊的关键字this
。 this
是一个指向class的指针,它提供了一个指向已为其调用成员函数的对象的指针。使用this
,您可以访问此类的所有(其他)成员 - 成员变量以及成员函数。
(几十年前,当我试图自己理解C ++和OOP是如何工作的时候,我看了一下编译后的汇编代码。我真的很惊讶地发现dot之前的对象就像其他参数一样处理完全在括号中。这是我个人的Heureka!-moments之一。)
可以在具有this->
的成员函数内部对(同一类的)成员进行访问,但是如果适用的话,编译器可以将其静默添加。
您的会员功能fraction::add()
实际上是对此的证明。
它有两个参数f1
和f2
,处理其成员(f1.num
,f1.den
,f2.num
和f2.den
)以执行添加分数,并存储分配。导致成员变量num
和den
。在这种情况下,num
与this->num
相同,den
与this->den
相同。那么,this
指向哪里?这取决于调用成员函数的对象。例如:
result.add(n, d);
在fraction::add()
内,this
将指向result
。