c++语言中引起二义性的问题之 构造函数不可小觑!

来源:互联网 发布:spring源码tx 编辑:程序博客网 时间:2024/05/21 23:17
本次讲述 在c++语言中引起二义性的问题之 构造函数不可小觑!
引发的实质是 函数的重载和默认参数值 所以一般的重载函数函数 也会出现这样的问题,今天以构造函数为例介绍的目的是捎带讲解一些构造函数的问


题!
#include <iostream>
using namespace std;
class a
{
      int n,j;// 注:当类中的成员没有设置访问权限的话,就会默认为: 私有的 ,这和 struct 有所不同 他会默认为:公有的类型! 
      public:
             a() //类的无参构造函数 
             {}//需要说明一下 就算是函数体为空的函数 也要有{}花括号否则就会报错的!但是好像 类的纯虚函数例外吧!
             a(int b,int m)//这里是类的有参构造函数
             {
                   b=n;
                   j=m; 
             } 
            
};
int main()
{
    a m(4,4);
    system("pause");
    return 0;
}


上面的这个程序 中有一个 无参构造函数 有一个类的有参构造函数,当在主函数里声明和定义类a 的对象的时候,要通过类的构造函数来给成员数据
初始化使用,但是类的构造函数的调用是隐式地在定义类的对象的时候自动的调用的,如果类中一个也没用声明和定义类的构造函数的话,就调用
类的默认构造函数 即缺省构造函数(无参构造函数),但是他什么也不做!此时 【类名 对象名】 这样定义对象!此时若用函数将类的成员数据


输出的话,将会输出一个任意的数值,因为你没有成功的将其初始化!


对于上面的程序来说引发错误 的原因在于 定义的时候:请看 a m 后面没有()就调用类的无参构造函数 (即对于调用无参构造函数来说,后面是不用加括号的,但是对于一般的函数来说是不行的!),a m(4, 5)此时就调用类的有参构造函数
但是 a m(4)时 编译器不能根据 对象后面的类型来选择调用对应的构造函数,(即 这个程序 构造函数也运用到了函数的重载机制!)。

看下面的程序代码:
#include <iostream>
using namespace std;
class a
{
      int n,j;
      public:
             a()
             {} 
             a(int b=1,int m=8) 这里是类的有全部默认参数值的构造函数
             {
                   b=n;
                   j=m; 
             } 
            
};
int main()
{
    a m; 看这里 用类a 定义了一个 对象 m
    system("pause");
    return 0;
}
这个程序你如果在a 的对象定义时将会出现许多的二义性问题(还有其他的小问题):
1: a m;
出错 因为本程序中存在一个类的有全部默认参数值的构造函数 当存在全部都是默认参数值的构造函数时调用全部都是默认参数值的构造函数时,类的对


象后面也不用加()但是赋的值是默认的参数值,也可以加()括号进行赋值从左到右依次赋值,没有的话就使用默认的参数值。
但是问题出现了: 对于 a m  这个语句来说 编译器分辨不出来到底调用哪个构造函数!,所以二义性就出现了!
解决的办法: 要么将 类的无参构造函数 要么不要使用这样的定义方式 a m 即可以这样 a(4),a(4,5);但是这样的话赋的值就是定义对象时提供参数,依次 从左向右赋值的。在此讲述一下函数的带有默认参数值问题:正如前面讲到的 函数的赋值是是依次 从左向右赋值的,所以说,如果一个函数的


形参被指定为默认值的话,那么位于他右侧的所有形参都必须指定默认值,也就是说在一个制定了的默认值的形参的后面跟随没有形参值的形参是不合法


的!原因不再多余解释!
回到这个程序来说 也就是说在这个情况下类的无参构造函数 是不能用了!


看下面这个程序:
#include <iostream>
using namespace std;
class a
{
      int n,j;
      public:
             a()
             {} 
             a(int v)
             a(int b,int m=8) 这里是类的有全部默认参数值的构造函数
             {
                   b=n;
                   j=m; 
             } 
            
};
int main()
{
    a m(4); 看这里 用类a 定义了一个 对象 m
    system("pause");
    return 0;
}
从上面的程序中看来无参数的构造函数是不会引起二义性了但是 其它的构造函数 改了 当这样 a m(4)时,第二个和第三个构造函数就会发生二义性的
的问题,怎么解决,要么这样定义a m(4 ,5) ,或者 a m不加括号,要么将第三个构造函数全部都定义为 有默认参数但是此时就只能 a m(4 ,5)调用


了,其它都会引发二义性的,要么将第三个构造函数全部都定义为 没有默认参数的此时就可以根据参数的数值,编译器就可以选择性的调用了!
对于这样类型的问题还有各式各样形式!
总之 这个引发二义性的问题 是由函数的重载加上默认参数值 共同引发的经过上面的讲述,请大家灵活的掌握!


另外:要说明的是当类中只要声明定义了一个构造函数那么以后类的默认构造函数即缺省构造函数就不再起作用,即使你的构造函数
是类的无参构造函数 !