Chinaunix首页 | 论坛 | 博客
  • 博客访问: 300129
  • 博文数量: 148
  • 博客积分: 4365
  • 博客等级: 上校
  • 技术积分: 1566
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 21:38
文章分类
文章存档

2014年(2)

2013年(45)

2012年(18)

2011年(1)

2009年(54)

2008年(28)

我的朋友

分类: C/C++

2008-09-05 22:28:26

我们没有定义自己的构造函数时,系统会提供一个默认的构造函数,默认的构造函数对于那些系统提供的类型,int,float等数据成员是直为它们分配内存存储空间,而不提供初始化值的,但是当对象定义在全局域时,系统会将这些数据成员初始化为它们默认的值。

class s12{
public:
//    s12(int a=2):i2(a),i(i2){

//        cout<<"start s12 constructor\n";

//        //cout<<"at beginning i is "<
//

//    }

//    s12( const s12 &obj){

//        cout<<"in s12 copy constructor\n";

//    }

    ~s12(){
        cout<<"in s12 destructor and i= "<<i<<endl;
    }
    int i;
    int i2;
};

s12 obj1;

int main(void) {

    s12 obj2;
    cout<<"obj1.i: "<<obj1.i<<endl;
    cout<<"obj2.i: "<<obj2.i<<endl;
    cout<<"end in main"<<endl;
}

注释掉自己的构造函数,使用系统提供的,在全局域定义一个对象obj1,在局部域定义对象obj2,结果为

obj1.i: 0
obj2.i: 2147319808
end in main
in s12 destructor and i= 2147319808
in s12 destructor and i= 0

obj1.i被初始化为int型默认值0,而obj2.i没有被初始化,为随机值。
所以每个类,最好都定义并实现自己的构造函数。

假设有一个类A,定义了自己的带有参数的构造函数,类B有一个类A的对象作为其数据成员,我们在创建类B的对象时,必须传进类A构造函数需要的参数,手动执行这个A对象的构造函数,因为A类在定义了这个带参数的构造函数后,已经没有系统为其提供的默认构造函数了。

class A{
public:
    A(int a){
    i=a;

    }
    int i;
};

class B{
public:
    int i;
    A in;
};

我们这时想创建B类的对象 B obj;编译器会报错,提示no matching function for call to `B::B()

我们将B类改为

class B{
public:

    B(){

    }
    int i;
    A in;
};

编译器会提示no matching function for call to `A::A(),应为我们定义了带参数的构造函数,所以找不到默认的了。在B的构造函数内我们应手动调用A的构造函数。

对于这样的类A,
1.不能作为动态分配的数组的元素类型。
2.作为静态数组元素类型时,必须为每个元素提供一个显式的初始化。
3.作为容器类型时,不能使用接受容器大小而没有同时提供一个元素初始化式的构造函数。

类类型的隐式转换与explicit关键字
看以下代码:

class C{
public:
    C():i(2){
        cout<<"in C first constructor\n";
    }
    C(int& refi){
        i=refi;
        cout<<"in C second constructor\n";
    }
    ~C(){
        cout<<"in C destructor\n";
    }
    void Compare(const C&);
private:
    int i;
};
void C::Compare(const C& refc){
    if(this->i>=refc.i)
        cout<<"my i >= refc.i "<<" refc.i: "<<refc.i<<endl;
    else
        cout<<"my i <= refc.i "<<" refc.i: "<<refc.i<<endl;
}

int main(){
    C obj1;
    int a=5;
    obj1.Compare(a);
    cout<<"end in main \n";
}

类C的Compare成员函数的参数是C类型的常引用,但我们在main函数里给其传进的是一个整形数a,程序却能良好运行,运行结果:

in C first constructor
in C second constructor
my i <= refc.i refc.i: 5
in C destructor
end in main
in C destructor

原因在于类C中的第二个构造函数的存在,使发生了隐式类类型转换,在运行结果的第二行我们可以看到。
这种构造函数的存在有时会造成程序混乱,解决方案是在其声明前加上关键字 explicit,该关键字只能被加到类内声明的构造函数之前。意为该构造函数只能显式的被调用。
将该函数修改为

    explicit C(int& refi){
        i=refi;
        cout<<"in C second constructor\n";
    }

编译,报错 no matching function for call to `C::Compare(int&)'。
如果还想达到原程序的效果,显示调用即可

obj1.Compare(C(a));

隐式转换不会用到非const 引用的初始化,但是可以用到const 引用的初始化。
如果希望某个运算的所有运算对象都能允许隐式转换,实现它的函数就应该作为
   非成员函数,取const X& 参数,非引用参数。
阅读(889) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~