【发布时间】:2020-08-26 19:21:15
【问题描述】:
对不起,篇幅较长,但我不知道如何在没有介绍的情况下提出这个问题。
让我们假设必须实现一个“数字”(class CNum 的对象),它可以是(有符号)整数 (∈ℤ) 或有理数 (∈ℚ)。
想象一下有一个成员函数prn 来打印数字。当然,我们希望以不同的方式打印整数和有理数。
一个典型的“old style”(C/ish)实现可能是这样的:
class CNum
{
public:
char type; // In this example, 'Q' or 'Z'.
[...]
char *prn(char *s)
{
if(type=='Z') sprintf(s,"something...."); else
if(type=='Q') sprintf(s,"something else ...");
return s;
}
[...]
};
更多“现代”(C++/ish)方法倾向于使用派生类和虚函数。 所以我会写这样的:
class CNum
{
public:
[...]
virtual char *prn(char *s) {....};
};
class ZZ : public CNum
{
long int n; // n is the value.
// implementation for integers, with proper prn()
};
class QQ : public CNum
{
long int a; unsigned long int b; // a/b is the value.
// implementation for rationals, with proper prn()
};
...而且看起来好多了(不是吗?)。
好的...现在,我需要将一个整数除以另一个整数的代码。 一般来说,两个整数之间的比率是有理数,所以我会写:
QQ operator / (ZZ &x, ZZ &y)
{
QQ R;
long int j;
if(y.n<0) {R.a=-x.n; R.b=-y.n;}
else {R.a= x.n; R.b= y.n;}
for(j=2; j<=abs(R.a) && j<=R.b; j++) while(!(R.a%j) && !(R.b%j)) {R.a/=j; R.b/=j;}
if(R.b==1) ; // (it's a whole number, stored as rational)(sorry...)
return R;
}
最长的行 (for(j...) 允许,例如,得到 2/3 而不是 2006/3009 的结果
那么,真正的问题来了:在if(R.b==1) 的情况下,如何返回class ZZ 类型的对象(而不是class QQ)?
在“old style”方法中这将是微不足道的。但这意味着所有成员函数都应该是 if(type==...){...} else if(type==...){...} else ... 的聚合——不是我想要维护的。
专家会有什么建议?
(我找到了一个返回对新对象的引用的解决方案,但它比问题更糟糕,否则它会泄漏内存)
另外:如果有人理解了这个问题(同样不知道答案):对更好的标题有什么建议吗?
【问题讨论】:
-
返回某种智能指针?
标签: c++ inheritance polymorphism