我对C++中重载函数的反思

3 篇文章 0 订阅

记得之前总结C++学习心得的时候,我在函数重载的地方有一句话是函数的重载不能通过返回值来确定,但是有例外,我当时没有想起那个特例,今天在学习JAVA的时候看到JAVA里面函数返回值可以区分函数重载的时候我想起了C++中的那个特例。首先,我们来看一下JAVA中函数重载时通过函数返回值来区分函数的例子,源程序如下:

package polymorphism;

class Grain {

       public String toString() {

              return "Grain";

       }

}

class Wheat extends Grain {

       public String toString() {

              return "Wheat";

       }

}

class Mill {

       Grain process() {

              return new Grain();

       }

}

class WheatMill extends Mill {

       //和基类的process()函数构成重载

       Wheat process() {

              return new Wheat();

       }

}

public class CovariantReturn {

       public static void main(String[] args){

              Mill m = new Mill();

              Grain g = m.process();

              System.out.println(g);

              m = new WheatMill(); //之前的引用对象被丢弃,由垃圾回收器负责回收

              g = m.process();     //基类的引用可以指向派生类对象,从而在下面打印时体现出多态

              System.out.println(g);

       }

}

上面JAVA源程序的输出结果如下:

Grain

Wheat

在上面的程序中我们看到基类Mill中函数的返回值类型是Grain,在其导出类中函数的返回值类型是Wheat,其中Wheat又是从Grain类中导出的,在WheatMill中两个process函数构成重载。在C++中我曾经也遇见过类似的情况,那么我们把上面的例子转换成C++code的话就写成下面的程序:

#include <iostream>

using namespace std;

class Grain

{

public:

    void print()

       {

              cout << "Crain" << endl;

       }

};

class Wheat : public Grain

{

public:

       void print()

       {

              cout << "Wheat" << endl;

       }

};

class Mill

{

public:

       Grain& process()

       {

              return obj;

       }

private:

       Grain obj;

};

class WheatMill : public Mill {

public:

       Wheat& process()

       {

              return obj;

       }

private:

       Wheat obj;

};

int main()

{

       WheatMill objWm;

       Mill objM;

 

       objWm.process().print();

       objM.process().print();

 

       return 0;

}

编译运行结果如下:

Wheat

Grain

下面我们通过这例子来展示一下C++中的多态,先看一个错误的例子:

#include <iostream>

using namespace std;

class Grain

{

public:

    void print()

       {

              cout << "Crain" << endl;

       }

};

 

class Wheat : public Grain

{

public:

       void print()

       {

              cout << "Wheat" << endl;

       }

};

class Mill

{

public:

       virtual Grain& process()

       {

              return obj;

       }

private:

       Grain obj;

};

class WheatMill : public Mill {

public:

       virtual Wheat& process()

       {

              return obj;

       }

private:

       Wheat obj;

};

int main()

{

       WheatMill objWm;

       Mill objM;

 

       objWm.process().print();

       objM.process().print();

 

       return 0;

}

不能把基类和派生类中的process函数声明为虚函数,这样不符合虚函数的书写规则,要想成为虚函数,基类中的函数是什么样子的在子类中也是什么样子的,但是在JAVA中不是这样规定的,上面的例子就是很好的证明。下面我们把print()函数声明为虚函数来体现多态性:

#include <iostream>

using namespace std;

class Grain

{

public:

    virtual void print()

       {

              cout << "Crain" << endl;

       }

};

 

class Wheat : public Grain

{

public:

       virtual void print()

       {

              cout << "Wheat" << endl;

       }

};

class Mill

{

public:

       Grain process()

       {

              return obj;

       }

private:

       Grain obj;

};

class WheatMill : public Mill {

public:

       Wheat process()

       {

              return obj;

       }

private:

       Wheat obj;

};

int main()

{

       WheatMill objWm;

       Mill objM;

 

       Grain &objG1 = objWm.process();

       objG1.print();

 

       Grain &objG2 = objM.process();

       objG2.print();

 

       return 0;

}

此时程序的输出结果是:

Wheat

Grain

在写上面两个程序的时候,我得出了一个结论:即引用是不可以被复制的,复制编译器不会报错,但是引用还是指向定义时初始化的那个对象,下面我们就来证明一下这个结论:

先看下面的程序:

#include <iostream>

using namespace std;

class Grain

{

public:

    virtual void print()

       {

              cout << "Crain" << endl;

       }

};

 

class Wheat : public Grain

{

public:

       virtual void print()

       {

              cout << "Wheat" << endl;

       }

};

int main()

{

       Grain obj1;

       Wheat obj2;

       Grain &obj3 = obj2;

       obj3.print();

       obj3 = obj1;           //给引用再次赋值

       obj3.print();

 

       return 0;

}

输出结果:

Wheat

Wheat

再看下面一段程序:

#include <iostream>

using namespace std;

class Grain

{

public:

    virtual void print()

       {

              cout << "Crain" << endl;

       }

};

 

class Wheat : public Grain

{

public:

       virtual void print()

       {

              cout << "Wheat" << endl;

       }

};

 

int main()

{

       Grain obj1;

       Wheat obj2;

       Grain &obj3 = obj1;

       obj3.print();

       obj3 = obj2;           //给引用再次赋值

       obj3.print();

 

       return 0;

}

输出结果:

Grain

Grain

在上面两段程序中我们都做了相同的一件事:先定义一个引用并且初始化,然后再对引用进行赋值,结果发现引用的赋值没有效果,也就是程序不会按照我们预期的那样显示正确结果,这样我们就证明了之前的那个结论:引用的赋值没有意义。学习中不要放过任何有疑问的地方,不懂就要把不懂的地方弄明白想清楚,这样在思考一个问题的时候我们可以想到很多类似的问题,正所谓温故而知新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值